29 #ifndef NLOHMANN_JSON_HPP 30 #define NLOHMANN_JSON_HPP 42 #include <initializer_list> 52 #include <type_traits> 57 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 58 #pragma GCC diagnostic push 59 #pragma GCC diagnostic ignored "-Wfloat-equal" 82 struct has_mapped_type
85 template<
typename C>
static char test(
typename C::mapped_type*);
86 template<
typename C>
static char (&test(...))[2];
88 static constexpr
bool value =
sizeof(test<T>(0)) == 1;
95 class DecimalSeparator :
public std::numpunct<char>
98 char do_decimal_point()
const 178 template<
typename U,
typename V,
typename... Args>
class ObjectType = std::map,
179 template<
typename U,
typename... Args>
class ArrayType = std::vector,
180 class StringType = std::string,
181 class BooleanType = bool,
182 class NumberIntegerType = std::int64_t,
183 class NumberUnsignedType = std::uint64_t,
184 class NumberFloatType = double,
185 template<
typename U>
class AllocatorType = std::allocator
229 using pointer =
typename std::allocator_traits<allocator_type>::pointer;
231 using const_pointer =
typename std::allocator_traits<allocator_type>::const_pointer;
344 using object_t = ObjectType<StringType,
346 std::less<StringType>,
347 AllocatorType<std::pair<
const StringType,
394 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
715 template<
typename T,
typename... Args>
716 static T* create(Args&& ... args)
718 AllocatorType<T> alloc;
719 auto deleter = [&](T * object)
721 alloc.deallocate(
object, 1);
723 std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
724 alloc.construct(
object.
get(), std::forward<Args>(args)...);
725 return object.release();
757 json_value() =
default;
759 json_value(
boolean_t v) noexcept : boolean(v) {}
771 case value_t::object:
773 object = create<object_t>();
779 array = create<array_t>();
783 case value_t::string:
785 string = create<string_t>(
"");
789 case value_t::boolean:
795 case value_t::number_integer:
801 case value_t::number_unsigned:
807 case value_t::number_float:
823 string = create<string_t>(value);
829 object = create<object_t>(value);
833 json_value(
const array_t& value)
835 array = create<array_t>(value);
918 using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
968 : m_type(value_type), m_value(value_type)
995 basic_json() =
default;
1043 : m_type(
value_t::object), m_value(val)
1072 template <
class CompatibleObjectType,
typename 1074 std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1075 std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value,
int>::type
1082 m_value.object = create<object_t>(begin(val), end(val));
1105 : m_type(
value_t::array), m_value(val)
1134 template <
class CompatibleArrayType,
typename 1136 not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1137 not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1138 not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1139 not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1140 not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1141 not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1142 std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value,
int>::type
1149 m_value.array = create<array_t>(begin(val), end(val));
1174 : m_type(
value_t::string), m_value(val)
1224 template <
class CompatibleStringType,
typename 1226 std::is_constructible<string_t, CompatibleStringType>::value,
int>::type
1247 : m_type(value_t::boolean), m_value(val)
1273 template<
typename T,
1274 typename std::enable_if<
1275 not (std::is_same<T, int>::value)
1276 and std::is_same<T, number_integer_t>::value
1280 : m_type(value_t::number_integer), m_value(val)
1309 : m_type(value_t::number_integer),
1310 m_value(static_cast<number_integer_t>(val))
1338 template<
typename CompatibleNumberIntegerType,
typename 1340 std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1341 std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1342 std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1343 CompatibleNumberIntegerType>::type
1346 : m_type(value_t::number_integer),
1347 m_value(static_cast<number_integer_t>(val))
1367 template<
typename T,
1368 typename std::enable_if<
1369 not (std::is_same<T, int>::value)
1370 and std::is_same<T, number_unsigned_t>::value
1374 : m_type(value_t::number_unsigned), m_value(val)
1397 template <
typename CompatibleNumberUnsignedType,
typename 1399 std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1400 std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1401 not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1402 CompatibleNumberUnsignedType>::type
1405 : m_type(value_t::number_unsigned),
1406 m_value(static_cast<number_unsigned_t>(val))
1434 : m_type(value_t::number_float), m_value(val)
1437 if (not std::isfinite(val))
1439 m_type = value_t::null;
1440 m_value = json_value();
1475 template<
typename CompatibleNumberFloatType,
typename =
typename 1477 std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1478 std::is_floating_point<CompatibleNumberFloatType>::value>::type
1554 bool type_deduction =
true,
1555 value_t manual_type = value_t::array)
1558 bool is_an_object =
true;
1562 for (
const auto& element : init)
1564 if (not element.is_array() or element.size() != 2
1565 or not element[0].is_string())
1569 is_an_object =
false;
1575 if (not type_deduction)
1578 if (manual_type == value_t::array)
1580 is_an_object =
false;
1584 if (manual_type == value_t::object and not is_an_object)
1586 throw std::domain_error(
"cannot create object from initializer list");
1593 m_type = value_t::object;
1594 m_value = value_t::object;
1596 assert(m_value.object !=
nullptr);
1598 for (
auto& element : init)
1600 m_value.object->emplace(*(element[0].m_value.string), element[1]);
1606 m_type = value_t::array;
1607 m_value.array = create<array_t>(init);
1645 static basic_json
array(std::initializer_list<basic_json> init =
1646 std::initializer_list<basic_json>())
1648 return basic_json(init,
false, value_t::array);
1685 static basic_json
object(std::initializer_list<basic_json> init =
1686 std::initializer_list<basic_json>())
1688 return basic_json(init,
false, value_t::object);
1712 m_value.array = create<array_t>(cnt, val);
1749 template <
class InputIT,
typename 1751 std::is_same<InputIT, typename basic_json_t::iterator>::value or
1752 std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1755 basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1758 if (first.m_object != last.m_object)
1760 throw std::domain_error(
"iterators are not compatible");
1766 case value_t::boolean:
1767 case value_t::number_float:
1768 case value_t::number_integer:
1769 case value_t::number_unsigned:
1770 case value_t::string:
1772 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1774 throw std::out_of_range(
"iterators out of range");
1787 case value_t::number_integer:
1789 assert(first.m_object !=
nullptr);
1790 m_value.number_integer = first.m_object->m_value.number_integer;
1794 case value_t::number_unsigned:
1796 assert(first.m_object !=
nullptr);
1797 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1801 case value_t::number_float:
1803 assert(first.m_object !=
nullptr);
1804 m_value.number_float = first.m_object->m_value.number_float;
1808 case value_t::boolean:
1810 assert(first.m_object !=
nullptr);
1811 m_value.boolean = first.m_object->m_value.boolean;
1815 case value_t::string:
1817 assert(first.m_object !=
nullptr);
1818 m_value = *first.m_object->m_value.string;
1822 case value_t::object:
1824 m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1828 case value_t::array:
1830 m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1836 assert(first.m_object !=
nullptr);
1837 throw std::domain_error(
"cannot use construct with iterators from " + first.m_object->type_name());
1864 *
this = parser(i, cb).parse();
1894 : m_type(other.m_type)
1898 case value_t::object:
1900 assert(other.m_value.object !=
nullptr);
1901 m_value = *other.m_value.object;
1905 case value_t::array:
1907 assert(other.m_value.array !=
nullptr);
1908 m_value = *other.m_value.array;
1912 case value_t::string:
1914 assert(other.m_value.string !=
nullptr);
1915 m_value = *other.m_value.string;
1919 case value_t::boolean:
1921 m_value = other.m_value.boolean;
1925 case value_t::number_integer:
1927 m_value = other.m_value.number_integer;
1931 case value_t::number_unsigned:
1933 m_value = other.m_value.number_unsigned;
1937 case value_t::number_float:
1939 m_value = other.m_value.number_float;
1969 : m_type(
std::move(other.m_type)),
1970 m_value(
std::move(other.m_value))
1973 other.m_type = value_t::null;
2001 std::is_nothrow_move_constructible<value_t>::value and
2002 std::is_nothrow_move_assignable<value_t>::value and
2003 std::is_nothrow_move_constructible<json_value>::value and
2004 std::is_nothrow_move_assignable<json_value>::value
2008 swap(m_type, other.m_type);
2009 swap(m_value, other.m_value);
2032 case value_t::object:
2034 AllocatorType<object_t> alloc;
2035 alloc.destroy(m_value.object);
2036 alloc.deallocate(m_value.object, 1);
2040 case value_t::array:
2042 AllocatorType<array_t> alloc;
2043 alloc.destroy(m_value.array);
2044 alloc.deallocate(m_value.array, 1);
2048 case value_t::string:
2050 AllocatorType<string_t> alloc;
2051 alloc.destroy(m_value.string);
2052 alloc.deallocate(m_value.string, 1);
2099 std::stringstream ss;
2103 dump(ss,
true, static_cast<unsigned int>(indent));
2163 return is_null() or is_string() or is_boolean() or is_number();
2190 return is_array() or is_object();
2212 return m_type == value_t::null;
2234 return m_type == value_t::boolean;
2264 return is_number_integer() or is_number_float();
2293 return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2321 return m_type == value_t::number_unsigned;
2349 return m_type == value_t::number_float;
2371 return m_type == value_t::object;
2393 return m_type == value_t::array;
2415 return m_type == value_t::string;
2442 return m_type == value_t::discarded;
2476 template <
class T,
typename 2478 std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2479 std::is_convertible<basic_json_t, typename T::mapped_type>::value
2481 T get_impl(T*)
const 2485 assert(m_value.object !=
nullptr);
2486 return T(m_value.object->begin(), m_value.object->end());
2490 throw std::domain_error(
"type must be object, but is " + type_name());
2499 assert(m_value.object !=
nullptr);
2500 return *(m_value.object);
2504 throw std::domain_error(
"type must be object, but is " + type_name());
2509 template <
class T,
typename 2511 std::is_convertible<basic_json_t, typename T::value_type>::value and
2512 not std::is_same<basic_json_t, typename T::value_type>::value and
2513 not std::is_arithmetic<T>::value and
2514 not std::is_convertible<std::string, T>::value and
2515 not has_mapped_type<T>::value
2517 T get_impl(T*)
const 2522 assert(m_value.array !=
nullptr);
2523 std::transform(m_value.array->begin(), m_value.array->end(),
2524 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2526 return i.
get<
typename T::value_type>();
2532 throw std::domain_error(
"type must be array, but is " + type_name());
2537 template <
class T,
typename 2539 std::is_convertible<basic_json_t, T>::value and
2540 not std::is_same<basic_json_t, T>::value
2542 std::vector<T> get_impl(std::vector<T>*)
const 2546 std::vector<T> to_vector;
2547 assert(m_value.array !=
nullptr);
2548 to_vector.reserve(m_value.array->size());
2549 std::transform(m_value.array->begin(), m_value.array->end(),
2550 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2558 throw std::domain_error(
"type must be array, but is " + type_name());
2563 template <
class T,
typename 2565 std::is_same<basic_json, typename T::value_type>::value and
2566 not has_mapped_type<T>::value
2568 T get_impl(T*)
const 2572 assert(m_value.array !=
nullptr);
2573 return T(m_value.array->begin(), m_value.array->end());
2577 throw std::domain_error(
"type must be array, but is " + type_name());
2586 assert(m_value.array !=
nullptr);
2587 return *(m_value.array);
2591 throw std::domain_error(
"type must be array, but is " + type_name());
2596 template <
typename T,
typename 2598 std::is_convertible<string_t, T>::value
2600 T get_impl(T*)
const 2604 assert(m_value.string !=
nullptr);
2605 return *m_value.string;
2609 throw std::domain_error(
"type must be string, but is " + type_name());
2614 template<
typename T,
typename 2616 std::is_arithmetic<T>::value
2618 T get_impl(T*)
const 2622 case value_t::number_integer:
2624 return static_cast<T
>(m_value.number_integer);
2627 case value_t::number_unsigned:
2629 return static_cast<T
>(m_value.number_unsigned);
2632 case value_t::number_float:
2634 return static_cast<T
>(m_value.number_float);
2639 throw std::domain_error(
"type must be number, but is " + type_name());
2649 :
throw std::domain_error(
"type must be boolean, but is " + type_name());
2655 return is_object() ? m_value.object :
nullptr;
2661 return is_object() ? m_value.object :
nullptr;
2667 return is_array() ? m_value.array :
nullptr;
2671 constexpr
const array_t* get_impl_ptr(
const array_t*)
const noexcept
2673 return is_array() ? m_value.array :
nullptr;
2679 return is_string() ? m_value.string :
nullptr;
2685 return is_string() ? m_value.string :
nullptr;
2691 return is_boolean() ? &m_value.boolean :
nullptr;
2697 return is_boolean() ? &m_value.boolean :
nullptr;
2703 return is_number_integer() ? &m_value.number_integer :
nullptr;
2709 return is_number_integer() ? &m_value.number_integer :
nullptr;
2715 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2721 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2727 return is_number_float() ? &m_value.number_float :
nullptr;
2733 return is_number_float() ? &m_value.number_float :
nullptr;
2747 template<
typename ReferenceType,
typename ThisType>
2748 static ReferenceType get_ref_impl(ThisType& obj)
2751 using PointerType =
typename std::add_pointer<ReferenceType>::type;
2752 auto ptr = obj.template get_ptr<PointerType>();
2760 throw std::domain_error(
"incompatible ReferenceType for get_ref, actual type is " +
2803 template<
typename ValueType,
typename 2805 not std::is_pointer<ValueType>::value
2807 ValueType
get()
const 2809 return get_impl(static_cast<ValueType*>(
nullptr));
2838 template<
typename PointerType,
typename 2840 std::is_pointer<PointerType>::value
2842 PointerType
get() noexcept
2845 return get_ptr<PointerType>();
2852 template<
typename PointerType,
typename 2854 std::is_pointer<PointerType>::value
2856 constexpr
const PointerType
get()
const noexcept
2859 return get_ptr<PointerType>();
2887 template<
typename PointerType,
typename 2889 std::is_pointer<PointerType>::value
2894 return get_impl_ptr(static_cast<PointerType>(
nullptr));
2901 template<
typename PointerType,
typename 2903 std::is_pointer<PointerType>::value
2904 and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2906 constexpr
const PointerType
get_ptr() const noexcept
2909 return get_impl_ptr(static_cast<const PointerType>(
nullptr));
2938 template<
typename ReferenceType,
typename 2940 std::is_reference<ReferenceType>::value
2945 return get_ref_impl<ReferenceType>(*this);
2952 template<
typename ReferenceType,
typename 2954 std::is_reference<ReferenceType>::value
2955 and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
2960 return get_ref_impl<ReferenceType>(*this);
2991 template <
typename ValueType,
typename 2993 not std::is_pointer<ValueType>::value
2994 and not std::is_same<ValueType, typename string_t::value_type>::value
2995 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015 2996 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
2999 operator ValueType()
const 3002 return get<ValueType>();
3044 assert(m_value.array !=
nullptr);
3045 return m_value.array->at(idx);
3047 catch (std::out_of_range&)
3050 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3055 throw std::domain_error(
"cannot use at() with " + type_name());
3088 assert(m_value.array !=
nullptr);
3089 return m_value.array->at(idx);
3091 catch (std::out_of_range&)
3094 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3099 throw std::domain_error(
"cannot use at() with " + type_name());
3136 assert(m_value.object !=
nullptr);
3137 return m_value.object->at(key);
3139 catch (std::out_of_range&)
3142 throw std::out_of_range(
"key '" + key +
"' not found");
3147 throw std::domain_error(
"cannot use at() with " + type_name());
3184 assert(m_value.object !=
nullptr);
3185 return m_value.object->at(key);
3187 catch (std::out_of_range&)
3190 throw std::out_of_range(
"key '" + key +
"' not found");
3195 throw std::domain_error(
"cannot use at() with " + type_name());
3229 m_type = value_t::array;
3230 m_value.
array = create<array_t>();
3237 assert(m_value.array !=
nullptr);
3238 for (
size_t i = m_value.array->size(); i <= idx; ++i)
3240 m_value.array->push_back(basic_json());
3243 return m_value.array->operator[](idx);
3247 throw std::domain_error(
"cannot use operator[] with " + type_name());
3275 assert(m_value.array !=
nullptr);
3276 return m_value.array->operator[](idx);
3280 throw std::domain_error(
"cannot use operator[] with " + type_name());
3316 m_type = value_t::object;
3317 m_value.
object = create<object_t>();
3323 assert(m_value.object !=
nullptr);
3324 return m_value.object->operator[](key);
3328 throw std::domain_error(
"cannot use operator[] with " + type_name());
3364 assert(m_value.object !=
nullptr);
3365 assert(m_value.object->find(key) != m_value.object->end());
3366 return m_value.object->find(key)->second;
3370 throw std::domain_error(
"cannot use operator[] with " + type_name());
3401 template<
typename T, std::
size_t n>
3404 return operator[](static_cast<const T>(key));
3436 template<
typename T, std::
size_t n>
3439 return operator[](static_cast<const T>(key));
3469 template<
typename T>
3475 m_type = value_t::object;
3476 m_value = value_t::object;
3482 assert(m_value.object !=
nullptr);
3483 return m_value.object->operator[](key);
3487 throw std::domain_error(
"cannot use operator[] with " + type_name());
3518 template<
typename T>
3524 assert(m_value.object !=
nullptr);
3525 assert(m_value.object->find(key) != m_value.object->end());
3526 return m_value.object->find(key)->second;
3530 throw std::domain_error(
"cannot use operator[] with " + type_name());
3582 template <
class ValueType,
typename 3584 std::is_convertible<basic_json_t, ValueType>::value
3586 ValueType
value(
const typename object_t::key_type& key, ValueType default_value)
const 3592 const auto it = find(key);
3599 return default_value;
3604 throw std::domain_error(
"cannot use value() with " + type_name());
3612 string_t value(
const typename object_t::key_type& key,
const char* default_value)
const 3614 return value(key,
string_t(default_value));
3745 template <
class InteratorType,
typename 3747 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3748 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3754 if (
this != pos.m_object)
3756 throw std::domain_error(
"iterator does not fit current value");
3759 InteratorType result = end();
3763 case value_t::boolean:
3764 case value_t::number_float:
3765 case value_t::number_integer:
3766 case value_t::number_unsigned:
3767 case value_t::string:
3769 if (not pos.m_it.primitive_iterator.is_begin())
3771 throw std::out_of_range(
"iterator out of range");
3776 delete m_value.string;
3777 m_value.string =
nullptr;
3780 m_type = value_t::null;
3784 case value_t::object:
3786 assert(m_value.object !=
nullptr);
3787 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3791 case value_t::array:
3793 assert(m_value.array !=
nullptr);
3794 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3800 throw std::domain_error(
"cannot use erase() with " + type_name());
3853 template <
class InteratorType,
typename 3855 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3856 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3859 InteratorType
erase(InteratorType first, InteratorType last)
3862 if (
this != first.m_object or
this != last.m_object)
3864 throw std::domain_error(
"iterators do not fit current value");
3867 InteratorType result = end();
3871 case value_t::boolean:
3872 case value_t::number_float:
3873 case value_t::number_integer:
3874 case value_t::number_unsigned:
3875 case value_t::string:
3877 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3879 throw std::out_of_range(
"iterators out of range");
3884 delete m_value.string;
3885 m_value.string =
nullptr;
3888 m_type = value_t::null;
3892 case value_t::object:
3894 assert(m_value.object !=
nullptr);
3895 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3896 last.m_it.object_iterator);
3900 case value_t::array:
3902 assert(m_value.array !=
nullptr);
3903 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3904 last.m_it.array_iterator);
3910 throw std::domain_error(
"cannot use erase() with " + type_name());
3951 assert(m_value.object !=
nullptr);
3952 return m_value.object->erase(key);
3956 throw std::domain_error(
"cannot use erase() with " + type_name());
3991 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3994 assert(m_value.array !=
nullptr);
3995 m_value.array->erase(m_value.array->begin() +
static_cast<difference_type>(idx));
3999 throw std::domain_error(
"cannot use erase() with " + type_name());
4033 auto result = end();
4037 assert(m_value.object !=
nullptr);
4038 result.m_it.object_iterator = m_value.object->find(key);
4050 auto result = cend();
4054 assert(m_value.object !=
nullptr);
4055 result.m_it.object_iterator = m_value.object->find(key);
4082 assert(not is_object() or m_value.object !=
nullptr);
4083 return is_object() ? m_value.object->count(key) : 0;
4371 template<
typename IteratorType>
class iteration_proxy;
4387 return iteration_proxy<iterator>(cont);
4395 return iteration_proxy<const_iterator>(cont);
4451 case value_t::array:
4453 assert(m_value.array !=
nullptr);
4454 return m_value.array->empty();
4457 case value_t::object:
4459 assert(m_value.object !=
nullptr);
4460 return m_value.object->empty();
4515 case value_t::array:
4517 assert(m_value.array !=
nullptr);
4518 return m_value.array->size();
4521 case value_t::object:
4523 assert(m_value.object !=
nullptr);
4524 return m_value.object->size();
4575 case value_t::array:
4577 assert(m_value.array !=
nullptr);
4578 return m_value.array->max_size();
4581 case value_t::object:
4583 assert(m_value.object !=
nullptr);
4584 return m_value.object->max_size();
4634 case value_t::number_integer:
4636 m_value.number_integer = 0;
4640 case value_t::number_unsigned:
4642 m_value.number_unsigned = 0;
4646 case value_t::number_float:
4648 m_value.number_float = 0.0;
4652 case value_t::boolean:
4654 m_value.boolean =
false;
4658 case value_t::string:
4660 assert(m_value.string !=
nullptr);
4661 m_value.string->clear();
4665 case value_t::array:
4667 assert(m_value.array !=
nullptr);
4668 m_value.array->clear();
4672 case value_t::object:
4674 assert(m_value.object !=
nullptr);
4675 m_value.object->clear();
4709 if (not(is_null() or is_array()))
4711 throw std::domain_error(
"cannot use push_back() with " + type_name());
4717 m_type = value_t::array;
4718 m_value = value_t::array;
4722 assert(m_value.array !=
nullptr);
4723 m_value.array->push_back(std::move(val));
4725 val.m_type = value_t::null;
4734 push_back(std::move(val));
4745 if (not(is_null() or is_array()))
4747 throw std::domain_error(
"cannot use push_back() with " + type_name());
4753 m_type = value_t::array;
4754 m_value = value_t::array;
4758 assert(m_value.array !=
nullptr);
4759 m_value.array->push_back(val);
4795 if (not(is_null() or is_object()))
4797 throw std::domain_error(
"cannot use push_back() with " + type_name());
4803 m_type = value_t::object;
4804 m_value = value_t::object;
4808 assert(m_value.object !=
nullptr);
4809 m_value.object->insert(val);
4849 if (is_object() and init.size() == 2 and init.begin()->is_string())
4851 const string_t key = *init.begin();
4852 push_back(
typename object_t::value_type(key, *(init.begin() + 1)));
4856 push_back(basic_json(init));
4898 if (pos.m_object !=
this)
4900 throw std::domain_error(
"iterator does not fit current value");
4905 assert(m_value.array !=
nullptr);
4906 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4911 throw std::domain_error(
"cannot use insert() with " + type_name());
4921 return insert(pos, val);
4954 if (pos.m_object !=
this)
4956 throw std::domain_error(
"iterator does not fit current value");
4961 assert(m_value.array !=
nullptr);
4962 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4967 throw std::domain_error(
"cannot use insert() with " + type_name());
5006 throw std::domain_error(
"cannot use insert() with " + type_name());
5010 if (pos.m_object !=
this)
5012 throw std::domain_error(
"iterator does not fit current value");
5016 if (first.m_object != last.m_object)
5018 throw std::domain_error(
"iterators do not fit");
5021 if (first.m_object ==
this or last.m_object ==
this)
5023 throw std::domain_error(
"passed iterators may not belong to container");
5028 assert(m_value.array !=
nullptr);
5029 result.m_it.array_iterator = m_value.array->insert(
5030 pos.m_it.array_iterator,
5031 first.m_it.array_iterator,
5032 last.m_it.array_iterator);
5065 throw std::domain_error(
"cannot use insert() with " + type_name());
5069 if (pos.m_object !=
this)
5071 throw std::domain_error(
"iterator does not fit current value");
5076 assert(m_value.array !=
nullptr);
5077 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5099 std::is_nothrow_move_constructible<value_t>::value and
5100 std::is_nothrow_move_assignable<value_t>::value and
5101 std::is_nothrow_move_constructible<json_value>::value and
5102 std::is_nothrow_move_assignable<json_value>::value
5105 std::swap(m_type, other.m_type);
5106 std::swap(m_value, other.m_value);
5134 assert(m_value.array !=
nullptr);
5135 std::swap(*(m_value.array), other);
5139 throw std::domain_error(
"cannot use swap() with " + type_name());
5168 assert(m_value.object !=
nullptr);
5169 std::swap(*(m_value.object), other);
5173 throw std::domain_error(
"cannot use swap() with " + type_name());
5202 assert(m_value.string !=
nullptr);
5203 std::swap(*(m_value.string), other);
5207 throw std::domain_error(
"cannot use swap() with " + type_name());
5233 static constexpr std::array<uint8_t, 8> order = {{
5246 if (lhs == value_t::discarded or rhs == value_t::discarded)
5251 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
5280 const auto lhs_type = lhs.type();
5281 const auto rhs_type = rhs.type();
5283 if (lhs_type == rhs_type)
5287 case value_t::array:
5289 assert(lhs.m_value.array !=
nullptr);
5290 assert(rhs.m_value.array !=
nullptr);
5291 return *lhs.m_value.array == *rhs.m_value.array;
5293 case value_t::object:
5295 assert(lhs.m_value.object !=
nullptr);
5296 assert(rhs.m_value.object !=
nullptr);
5297 return *lhs.m_value.object == *rhs.m_value.object;
5303 case value_t::string:
5305 assert(lhs.m_value.string !=
nullptr);
5306 assert(rhs.m_value.string !=
nullptr);
5307 return *lhs.m_value.string == *rhs.m_value.string;
5309 case value_t::boolean:
5311 return lhs.m_value.boolean == rhs.m_value.boolean;
5313 case value_t::number_integer:
5315 return lhs.m_value.number_integer == rhs.m_value.number_integer;
5317 case value_t::number_unsigned:
5319 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5321 case value_t::number_float:
5323 return lhs.m_value.number_float == rhs.m_value.number_float;
5331 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5333 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5335 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5337 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_integer);
5339 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5341 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5343 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5345 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5347 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5349 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5351 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5353 return lhs.m_value.number_integer ==
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5409 return not (lhs == rhs);
5441 return not v.is_null();
5470 const auto lhs_type = lhs.type();
5471 const auto rhs_type = rhs.type();
5473 if (lhs_type == rhs_type)
5477 case value_t::array:
5479 assert(lhs.m_value.array !=
nullptr);
5480 assert(rhs.m_value.array !=
nullptr);
5481 return *lhs.m_value.array < *rhs.m_value.array;
5483 case value_t::object:
5485 assert(lhs.m_value.object !=
nullptr);
5486 assert(rhs.m_value.object !=
nullptr);
5487 return *lhs.m_value.object < *rhs.m_value.object;
5493 case value_t::string:
5495 assert(lhs.m_value.string !=
nullptr);
5496 assert(rhs.m_value.string !=
nullptr);
5497 return *lhs.m_value.string < *rhs.m_value.string;
5499 case value_t::boolean:
5501 return lhs.m_value.boolean < rhs.m_value.boolean;
5503 case value_t::number_integer:
5505 return lhs.m_value.number_integer < rhs.m_value.number_integer;
5507 case value_t::number_unsigned:
5509 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5511 case value_t::number_float:
5513 return lhs.m_value.number_float < rhs.m_value.number_float;
5521 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5523 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5525 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5527 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_integer);
5529 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5531 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5533 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5535 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5537 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5539 return lhs.m_value.number_integer <
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5541 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5543 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5549 return operator<(lhs_type, rhs_type);
5571 return not (rhs < lhs);
5593 return not (lhs <= rhs);
5615 return not (lhs < rhs);
5650 friend std::ostream&
operator<<(std::ostream& o,
const basic_json& j)
5653 const bool pretty_print = (o.width() > 0);
5654 const auto indentation = (pretty_print ? o.width() : 0);
5660 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
5668 friend std::ostream&
operator>>(
const basic_json& j, std::ostream& o)
5709 return parser(s, cb).
parse();
5738 return parser(i, cb).
parse();
5746 return parser(i, cb).
parse();
5774 j = parser(i).
parse();
5784 j = parser(i).
parse();
5797 string_t type_name()
const noexcept
5803 case value_t::object:
5805 case value_t::array:
5807 case value_t::string:
5809 case value_t::boolean:
5811 case value_t::discarded:
5826 static std::size_t extra_space(
const string_t& s) noexcept
5828 std::size_t result = 0;
5830 for (
const auto& c : s)
5849 if (c >= 0x00 and c <= 0x1f)
5877 const auto space = extra_space(s);
5884 string_t result(s.size() + space,
'\\');
5885 std::size_t pos = 0;
5887 for (
const auto& c : s)
5894 result[pos + 1] =
'"';
5910 result[pos + 1] =
'b';
5918 result[pos + 1] =
'f';
5926 result[pos + 1] =
'n';
5934 result[pos + 1] =
'r';
5942 result[pos + 1] =
't';
5949 if (c >= 0x00 and c <= 0x1f)
5953 const auto hexify = [](
const int v) ->
char 5956 ? (
'0' +
static_cast<char>(v))
5957 : (
'a' +
static_cast<char>((v - 10) & 0x1f));
5962 {
'u',
'0',
'0', hexify(c >> 4), hexify(c & 0x0f)
6000 void dump(std::ostream& o,
6001 const bool pretty_print,
6002 const unsigned int indent_step,
6003 const unsigned int current_indent = 0)
const 6006 unsigned int new_indent = current_indent;
6010 case value_t::object:
6012 assert(m_value.object !=
nullptr);
6014 if (m_value.object->empty())
6025 new_indent += indent_step;
6029 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
6031 if (i != m_value.object->cbegin())
6033 o << (pretty_print ?
",\n" :
",");
6035 o <<
string_t(new_indent,
' ') <<
"\"" 6036 << escape_string(i->first) <<
"\":" 6037 << (pretty_print ?
" " :
"");
6038 i->second.dump(o, pretty_print, indent_step, new_indent);
6044 new_indent -= indent_step;
6048 o <<
string_t(new_indent,
' ') +
"}";
6052 case value_t::array:
6054 assert(m_value.array !=
nullptr);
6056 if (m_value.array->empty())
6067 new_indent += indent_step;
6071 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6073 if (i != m_value.array->cbegin())
6075 o << (pretty_print ?
",\n" :
",");
6078 i->dump(o, pretty_print, indent_step, new_indent);
6084 new_indent -= indent_step;
6088 o <<
string_t(new_indent,
' ') <<
"]";
6092 case value_t::string:
6094 assert(m_value.string !=
nullptr);
6095 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
6099 case value_t::boolean:
6101 o << (m_value.boolean ?
"true" :
"false");
6105 case value_t::number_integer:
6107 o << m_value.number_integer;
6111 case value_t::number_unsigned:
6113 o << m_value.number_unsigned;
6117 case value_t::number_float:
6119 if (m_value.number_float == 0)
6122 o << (std::signbit(m_value.number_float) ?
"-0.0" :
"0.0");
6131 std::stringstream ss;
6132 ss.imbue(std::locale(std::locale(),
new DecimalSeparator));
6133 ss << std::setprecision(std::numeric_limits<double>::digits10)
6134 << m_value.number_float;
6140 case value_t::discarded:
6160 value_t m_type = value_t::null;
6163 json_value m_value = {};
6180 class primitive_iterator_t
6184 void set_begin() noexcept
6190 void set_end() noexcept
6196 constexpr
bool is_begin()
const noexcept
6198 return (m_it == begin_value);
6202 constexpr
bool is_end()
const noexcept
6204 return (m_it == end_value);
6224 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6234 struct internal_iterator
6237 typename object_t::iterator object_iterator;
6239 typename array_t::iterator array_iterator;
6241 primitive_iterator_t primitive_iterator;
6244 internal_iterator() noexcept
6245 : object_iterator(), array_iterator(), primitive_iterator()
6250 template<
typename IteratorType>
6251 class iteration_proxy
6255 class iteration_proxy_internal
6259 IteratorType anchor;
6261 size_t array_index = 0;
6264 explicit iteration_proxy_internal(IteratorType it) noexcept
6269 iteration_proxy_internal& operator*()
6275 iteration_proxy_internal& operator++()
6284 bool operator!= (
const iteration_proxy_internal& o)
const 6286 return anchor != o.anchor;
6292 assert(anchor.m_object !=
nullptr);
6294 switch (anchor.m_object->type())
6297 case value_t::array:
6299 return std::to_string(array_index);
6303 case value_t::object:
6305 return anchor.key();
6317 typename IteratorType::reference value()
const 6319 return anchor.value();
6324 typename IteratorType::reference container;
6328 explicit iteration_proxy(
typename IteratorType::reference cont)
6333 iteration_proxy_internal begin() noexcept
6335 return iteration_proxy_internal(container.begin());
6339 iteration_proxy_internal end() noexcept
6341 return iteration_proxy_internal(container.end());
6359 class const_iterator :
public std::iterator<std::random_access_iterator_tag, const basic_json>
6362 friend class basic_json;
6383 assert(m_object !=
nullptr);
6385 switch (m_object->m_type)
6389 m_it.object_iterator =
typename object_t::iterator();
6395 m_it.array_iterator =
typename array_t::iterator();
6401 m_it.primitive_iterator = primitive_iterator_t();
6409 : m_object(other.m_object)
6411 assert(m_object !=
nullptr);
6413 switch (m_object->m_type)
6417 m_it.object_iterator = other.m_it.object_iterator;
6423 m_it.array_iterator = other.m_it.array_iterator;
6429 m_it.primitive_iterator = other.m_it.primitive_iterator;
6437 : m_object(other.m_object), m_it(other.m_it)
6442 std::is_nothrow_move_constructible<pointer>::value and
6443 std::is_nothrow_move_assignable<pointer>::value and
6444 std::is_nothrow_move_constructible<internal_iterator>::value and
6445 std::is_nothrow_move_assignable<internal_iterator>::value
6448 std::swap(m_object, other.m_object);
6449 std::swap(m_it, other.m_it);
6455 void set_begin() noexcept
6457 assert(m_object !=
nullptr);
6459 switch (m_object->m_type)
6463 assert(m_object->m_value.object !=
nullptr);
6464 m_it.object_iterator = m_object->m_value.object->begin();
6470 assert(m_object->m_value.array !=
nullptr);
6471 m_it.array_iterator = m_object->m_value.array->begin();
6478 m_it.primitive_iterator.set_end();
6484 m_it.primitive_iterator.set_begin();
6491 void set_end() noexcept
6493 assert(m_object !=
nullptr);
6495 switch (m_object->m_type)
6499 assert(m_object->m_value.object !=
nullptr);
6500 m_it.object_iterator = m_object->m_value.object->end();
6506 assert(m_object->m_value.array !=
nullptr);
6507 m_it.array_iterator = m_object->m_value.array->end();
6513 m_it.primitive_iterator.set_end();
6523 assert(m_object !=
nullptr);
6525 switch (m_object->m_type)
6529 assert(m_object->m_value.object);
6530 assert(m_it.object_iterator != m_object->m_value.object->end());
6531 return m_it.object_iterator->second;
6536 assert(m_object->m_value.array);
6537 assert(m_it.array_iterator != m_object->m_value.array->end());
6538 return *m_it.array_iterator;
6543 throw std::out_of_range(
"cannot get value");
6548 if (m_it.primitive_iterator.is_begin())
6554 throw std::out_of_range(
"cannot get value");
6563 assert(m_object !=
nullptr);
6565 switch (m_object->m_type)
6569 assert(m_object->m_value.object);
6570 assert(m_it.object_iterator != m_object->m_value.object->end());
6571 return &(m_it.object_iterator->second);
6576 assert(m_object->m_value.array);
6577 assert(m_it.array_iterator != m_object->m_value.array->end());
6578 return &*m_it.array_iterator;
6583 if (m_it.primitive_iterator.is_begin())
6589 throw std::out_of_range(
"cannot get value");
6598 auto result = *
this;
6606 assert(m_object !=
nullptr);
6608 switch (m_object->m_type)
6612 ++m_it.object_iterator;
6618 ++m_it.array_iterator;
6624 ++m_it.primitive_iterator;
6635 auto result = *
this;
6643 assert(m_object !=
nullptr);
6645 switch (m_object->m_type)
6649 --m_it.object_iterator;
6655 --m_it.array_iterator;
6661 --m_it.primitive_iterator;
6673 if (m_object != other.m_object)
6675 throw std::domain_error(
"cannot compare iterators of different containers");
6678 assert(m_object !=
nullptr);
6680 switch (m_object->m_type)
6684 return (m_it.object_iterator == other.m_it.object_iterator);
6689 return (m_it.array_iterator == other.m_it.array_iterator);
6694 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6702 return not operator==(other);
6709 if (m_object != other.m_object)
6711 throw std::domain_error(
"cannot compare iterators of different containers");
6714 assert(m_object !=
nullptr);
6716 switch (m_object->m_type)
6720 throw std::domain_error(
"cannot compare order of object iterators");
6725 return (m_it.array_iterator < other.m_it.array_iterator);
6730 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6738 return not other.operator < (*this);
6744 return not operator<=(other);
6750 return not operator<(other);
6756 assert(m_object !=
nullptr);
6758 switch (m_object->m_type)
6762 throw std::domain_error(
"cannot use offsets with object iterators");
6767 m_it.array_iterator += i;
6773 m_it.primitive_iterator += i;
6784 return operator+=(-i);
6790 auto result = *
this;
6798 auto result = *
this;
6806 assert(m_object !=
nullptr);
6808 switch (m_object->m_type)
6812 throw std::domain_error(
"cannot use offsets with object iterators");
6817 return m_it.array_iterator - other.m_it.array_iterator;
6822 return m_it.primitive_iterator - other.m_it.primitive_iterator;
6830 assert(m_object !=
nullptr);
6832 switch (m_object->m_type)
6836 throw std::domain_error(
"cannot use operator[] for object iterators");
6841 return *(m_it.array_iterator + n);
6846 throw std::out_of_range(
"cannot get value");
6851 if (m_it.primitive_iterator == -n)
6857 throw std::out_of_range(
"cannot get value");
6864 typename object_t::key_type
key()
const 6866 assert(m_object !=
nullptr);
6868 if (m_object->is_object())
6870 return m_it.object_iterator->first;
6874 throw std::domain_error(
"cannot use key() for non-object iterators");
6888 internal_iterator m_it = internal_iterator();
6925 std::is_nothrow_move_constructible<pointer>::value and
6926 std::is_nothrow_move_assignable<pointer>::value and
6927 std::is_nothrow_move_constructible<internal_iterator>::value and
6928 std::is_nothrow_move_assignable<internal_iterator>::value
6931 base_iterator::operator=(other);
6938 return const_cast<reference>(base_iterator::operator*());
6944 return const_cast<pointer>(base_iterator::operator->());
6951 base_iterator::operator++();
6958 base_iterator::operator++();
6966 base_iterator::operator--();
6973 base_iterator::operator--();
6980 base_iterator::operator+=(i);
6987 base_iterator::operator-=(i);
6994 auto result = *
this;
7002 auto result = *
this;
7010 return base_iterator::operator-(other);
7016 return const_cast<reference>(base_iterator::operator[](n));
7022 return const_cast<reference>(base_iterator::value());
7043 template<
typename Base>
7065 return base_iterator::operator++(1);
7071 base_iterator::operator++();
7078 return base_iterator::operator--(1);
7084 base_iterator::operator--();
7091 base_iterator::operator+=(i);
7098 auto result = *
this;
7106 auto result = *
this;
7114 return this->base() - other.base();
7120 return *(this->operator+(n));
7124 typename object_t::key_type
key()
const 7126 auto it = --this->base();
7133 auto it = --this->base();
7134 return it.operator * ();
7155 enum class token_type
7174 using lexer_char_t =
unsigned char;
7177 explicit lexer(
const string_t& s) noexcept
7178 : m_stream(
nullptr), m_buffer(s)
7180 m_content =
reinterpret_cast<const lexer_char_t*
>(s.c_str());
7181 assert(m_content !=
nullptr);
7182 m_start = m_cursor = m_content;
7183 m_limit = m_content + s.size();
7187 explicit lexer(std::istream* s) noexcept
7188 : m_stream(s), m_buffer()
7190 assert(m_stream !=
nullptr);
7191 getline(*m_stream, m_buffer);
7192 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
7193 assert(m_content !=
nullptr);
7194 m_start = m_cursor = m_content;
7195 m_limit = m_content + m_buffer.size();
7202 lexer(
const lexer&) =
delete;
7203 lexer operator=(
const lexer&) =
delete;
7220 static string_t to_unicode(
const std::size_t codepoint1,
7221 const std::size_t codepoint2 = 0)
7224 std::size_t codepoint = codepoint1;
7227 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7230 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7244 throw std::invalid_argument(
"missing or wrong low surrogate");
7250 if (codepoint < 0x80)
7253 result.append(1, static_cast<typename string_t::value_type>(codepoint));
7255 else if (codepoint <= 0x7ff)
7258 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7259 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7261 else if (codepoint <= 0xffff)
7264 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7265 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7266 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7268 else if (codepoint <= 0x10ffff)
7271 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7272 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7273 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7274 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7278 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
7285 static std::string token_type_name(token_type t)
7289 case token_type::uninitialized:
7290 return "<uninitialized>";
7291 case token_type::literal_true:
7292 return "true literal";
7293 case token_type::literal_false:
7294 return "false literal";
7295 case token_type::literal_null:
7296 return "null literal";
7297 case token_type::value_string:
7298 return "string literal";
7299 case token_type::value_number:
7300 return "number literal";
7301 case token_type::begin_array:
7303 case token_type::begin_object:
7305 case token_type::end_array:
7307 case token_type::end_object:
7309 case token_type::name_separator:
7311 case token_type::value_separator:
7313 case token_type::parse_error:
7314 return "<parse error>";
7315 case token_type::end_of_input:
7316 return "end of input";
7320 return "unknown token";
7335 token_type scan() noexcept
7342 assert(m_start !=
nullptr);
7347 unsigned int yyaccept = 0;
7348 static const unsigned char yybm[] =
7350 0, 0, 0, 0, 0, 0, 0, 0,
7351 0, 32, 32, 0, 0, 32, 0, 0,
7352 128, 128, 128, 128, 128, 128, 128, 128,
7353 128, 128, 128, 128, 128, 128, 128, 128,
7354 160, 128, 0, 128, 128, 128, 128, 128,
7355 128, 128, 128, 128, 128, 128, 128, 128,
7356 192, 192, 192, 192, 192, 192, 192, 192,
7357 192, 192, 128, 128, 128, 128, 128, 128,
7358 128, 128, 128, 128, 128, 128, 128, 128,
7359 128, 128, 128, 128, 128, 128, 128, 128,
7360 128, 128, 128, 128, 128, 128, 128, 128,
7361 128, 128, 128, 128, 0, 128, 128, 128,
7362 128, 128, 128, 128, 128, 128, 128, 128,
7363 128, 128, 128, 128, 128, 128, 128, 128,
7364 128, 128, 128, 128, 128, 128, 128, 128,
7365 128, 128, 128, 128, 128, 128, 128, 128,
7366 128, 128, 128, 128, 128, 128, 128, 128,
7367 128, 128, 128, 128, 128, 128, 128, 128,
7368 128, 128, 128, 128, 128, 128, 128, 128,
7369 128, 128, 128, 128, 128, 128, 128, 128,
7370 128, 128, 128, 128, 128, 128, 128, 128,
7371 128, 128, 128, 128, 128, 128, 128, 128,
7372 128, 128, 128, 128, 128, 128, 128, 128,
7373 128, 128, 128, 128, 128, 128, 128, 128,
7374 128, 128, 128, 128, 128, 128, 128, 128,
7375 128, 128, 128, 128, 128, 128, 128, 128,
7376 128, 128, 128, 128, 128, 128, 128, 128,
7377 128, 128, 128, 128, 128, 128, 128, 128,
7378 128, 128, 128, 128, 128, 128, 128, 128,
7379 128, 128, 128, 128, 128, 128, 128, 128,
7380 128, 128, 128, 128, 128, 128, 128, 128,
7381 128, 128, 128, 128, 128, 128, 128, 128,
7383 if ((m_limit - m_cursor) < 5)
7388 if (yybm[0 + yych] & 32)
7390 goto basic_json_parser_6;
7400 goto basic_json_parser_2;
7404 goto basic_json_parser_4;
7406 goto basic_json_parser_9;
7412 goto basic_json_parser_4;
7416 goto basic_json_parser_10;
7418 goto basic_json_parser_12;
7427 goto basic_json_parser_4;
7431 goto basic_json_parser_13;
7433 goto basic_json_parser_15;
7439 goto basic_json_parser_17;
7443 goto basic_json_parser_19;
7445 goto basic_json_parser_4;
7457 goto basic_json_parser_21;
7461 goto basic_json_parser_4;
7463 goto basic_json_parser_23;
7469 goto basic_json_parser_24;
7473 goto basic_json_parser_4;
7475 goto basic_json_parser_25;
7484 goto basic_json_parser_26;
7486 goto basic_json_parser_4;
7492 goto basic_json_parser_28;
7496 goto basic_json_parser_30;
7498 goto basic_json_parser_4;
7502 basic_json_parser_2:
7505 return token_type::end_of_input;
7507 basic_json_parser_4:
7509 basic_json_parser_5:
7511 return token_type::parse_error;
7513 basic_json_parser_6:
7515 if (m_limit <= m_cursor)
7520 if (yybm[0 + yych] & 32)
7522 goto basic_json_parser_6;
7527 basic_json_parser_9:
7529 yych = *(m_marker = ++m_cursor);
7532 goto basic_json_parser_5;
7534 goto basic_json_parser_32;
7535 basic_json_parser_10:
7538 return token_type::value_separator;
7540 basic_json_parser_12:
7544 goto basic_json_parser_5;
7548 goto basic_json_parser_13;
7552 goto basic_json_parser_15;
7554 goto basic_json_parser_5;
7555 basic_json_parser_13:
7557 yych = *(m_marker = ++m_cursor);
7562 goto basic_json_parser_37;
7569 goto basic_json_parser_38;
7573 goto basic_json_parser_38;
7576 basic_json_parser_14:
7578 return token_type::value_number;
7580 basic_json_parser_15:
7582 m_marker = ++m_cursor;
7583 if ((m_limit - m_cursor) < 3)
7588 if (yybm[0 + yych] & 64)
7590 goto basic_json_parser_15;
7596 goto basic_json_parser_37;
7598 goto basic_json_parser_14;
7604 goto basic_json_parser_38;
7608 goto basic_json_parser_38;
7610 goto basic_json_parser_14;
7612 basic_json_parser_17:
7615 return token_type::name_separator;
7617 basic_json_parser_19:
7620 return token_type::begin_array;
7622 basic_json_parser_21:
7625 return token_type::end_array;
7627 basic_json_parser_23:
7629 yych = *(m_marker = ++m_cursor);
7632 goto basic_json_parser_39;
7634 goto basic_json_parser_5;
7635 basic_json_parser_24:
7637 yych = *(m_marker = ++m_cursor);
7640 goto basic_json_parser_40;
7642 goto basic_json_parser_5;
7643 basic_json_parser_25:
7645 yych = *(m_marker = ++m_cursor);
7648 goto basic_json_parser_41;
7650 goto basic_json_parser_5;
7651 basic_json_parser_26:
7654 return token_type::begin_object;
7656 basic_json_parser_28:
7659 return token_type::end_object;
7661 basic_json_parser_30:
7663 yych = *(m_marker = ++m_cursor);
7666 goto basic_json_parser_42;
7668 goto basic_json_parser_5;
7669 basic_json_parser_31:
7671 if (m_limit <= m_cursor)
7676 basic_json_parser_32:
7677 if (yybm[0 + yych] & 128)
7679 goto basic_json_parser_31;
7683 goto basic_json_parser_33;
7687 goto basic_json_parser_34;
7689 goto basic_json_parser_36;
7690 basic_json_parser_33:
7691 m_cursor = m_marker;
7694 goto basic_json_parser_5;
7698 goto basic_json_parser_14;
7700 basic_json_parser_34:
7703 return token_type::value_string;
7705 basic_json_parser_36:
7707 if (m_limit <= m_cursor)
7718 goto basic_json_parser_31;
7722 goto basic_json_parser_33;
7724 goto basic_json_parser_31;
7732 goto basic_json_parser_33;
7734 goto basic_json_parser_31;
7740 goto basic_json_parser_31;
7742 goto basic_json_parser_33;
7752 goto basic_json_parser_31;
7756 goto basic_json_parser_31;
7758 goto basic_json_parser_33;
7766 goto basic_json_parser_31;
7768 goto basic_json_parser_33;
7774 goto basic_json_parser_31;
7778 goto basic_json_parser_43;
7780 goto basic_json_parser_33;
7784 basic_json_parser_37:
7788 goto basic_json_parser_33;
7792 goto basic_json_parser_44;
7794 goto basic_json_parser_33;
7795 basic_json_parser_38:
7801 goto basic_json_parser_46;
7803 goto basic_json_parser_33;
7809 goto basic_json_parser_46;
7813 goto basic_json_parser_33;
7817 goto basic_json_parser_47;
7819 goto basic_json_parser_33;
7821 basic_json_parser_39:
7825 goto basic_json_parser_49;
7827 goto basic_json_parser_33;
7828 basic_json_parser_40:
7832 goto basic_json_parser_50;
7834 goto basic_json_parser_33;
7835 basic_json_parser_41:
7839 goto basic_json_parser_51;
7841 goto basic_json_parser_33;
7842 basic_json_parser_42:
7846 goto basic_json_parser_52;
7848 goto basic_json_parser_33;
7849 basic_json_parser_43:
7851 if (m_limit <= m_cursor)
7860 goto basic_json_parser_33;
7864 goto basic_json_parser_54;
7866 goto basic_json_parser_33;
7872 goto basic_json_parser_54;
7876 goto basic_json_parser_33;
7880 goto basic_json_parser_54;
7882 goto basic_json_parser_33;
7884 basic_json_parser_44:
7886 m_marker = ++m_cursor;
7887 if ((m_limit - m_cursor) < 3)
7896 goto basic_json_parser_14;
7900 goto basic_json_parser_44;
7902 goto basic_json_parser_14;
7908 goto basic_json_parser_38;
7912 goto basic_json_parser_38;
7914 goto basic_json_parser_14;
7916 basic_json_parser_46:
7920 goto basic_json_parser_33;
7924 goto basic_json_parser_33;
7926 basic_json_parser_47:
7928 if (m_limit <= m_cursor)
7935 goto basic_json_parser_14;
7939 goto basic_json_parser_47;
7941 goto basic_json_parser_14;
7942 basic_json_parser_49:
7946 goto basic_json_parser_55;
7948 goto basic_json_parser_33;
7949 basic_json_parser_50:
7953 goto basic_json_parser_56;
7955 goto basic_json_parser_33;
7956 basic_json_parser_51:
7960 goto basic_json_parser_58;
7962 goto basic_json_parser_33;
7963 basic_json_parser_52:
7968 basic_json_parser_54:
7970 if (m_limit <= m_cursor)
7979 goto basic_json_parser_33;
7983 goto basic_json_parser_60;
7985 goto basic_json_parser_33;
7991 goto basic_json_parser_60;
7995 goto basic_json_parser_33;
7999 goto basic_json_parser_60;
8001 goto basic_json_parser_33;
8003 basic_json_parser_55:
8007 goto basic_json_parser_61;
8009 goto basic_json_parser_33;
8010 basic_json_parser_56:
8013 return token_type::literal_null;
8015 basic_json_parser_58:
8018 return token_type::literal_true;
8020 basic_json_parser_60:
8022 if (m_limit <= m_cursor)
8031 goto basic_json_parser_33;
8035 goto basic_json_parser_63;
8037 goto basic_json_parser_33;
8043 goto basic_json_parser_63;
8047 goto basic_json_parser_33;
8051 goto basic_json_parser_63;
8053 goto basic_json_parser_33;
8055 basic_json_parser_61:
8058 return token_type::literal_false;
8060 basic_json_parser_63:
8062 if (m_limit <= m_cursor)
8071 goto basic_json_parser_33;
8075 goto basic_json_parser_31;
8077 goto basic_json_parser_33;
8083 goto basic_json_parser_31;
8087 goto basic_json_parser_33;
8091 goto basic_json_parser_31;
8093 goto basic_json_parser_33;
8100 void yyfill() noexcept
8102 if (m_stream ==
nullptr or not * m_stream)
8107 const auto offset_start = m_start - m_content;
8108 const auto offset_marker = m_marker - m_start;
8109 const auto offset_cursor = m_cursor - m_start;
8111 m_buffer.erase(0, static_cast<size_t>(offset_start));
8113 assert(m_stream !=
nullptr);
8114 std::getline(*m_stream, line);
8115 m_buffer +=
"\n" + line;
8117 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
8118 assert(m_content !=
nullptr);
8119 m_start = m_content;
8120 m_marker = m_start + offset_marker;
8121 m_cursor = m_start + offset_cursor;
8122 m_limit = m_start + m_buffer.size() - 1;
8128 assert(m_start !=
nullptr);
8129 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8130 static_cast<size_t>(m_cursor - m_start));
8158 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8161 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8217 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8218 4).c_str(),
nullptr, 16);
8221 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8224 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
8226 throw std::invalid_argument(
"missing low surrogate");
8230 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8231 (i + 7), 4).c_str(),
nullptr, 16);
8232 result += to_unicode(codepoint, codepoint2);
8239 result += to_unicode(codepoint);
8251 result.append(1, static_cast<typename string_t::value_type>(*i));
8278 long double str_to_float_t(
long double* ,
char** endptr)
const 8280 return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8298 double str_to_float_t(
double* ,
char** endptr)
const 8300 return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8318 float str_to_float_t(
float* ,
char** endptr)
const 8320 return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8344 void get_number(basic_json& result)
const 8346 assert(m_start !=
nullptr);
8348 const lexer::lexer_char_t* curptr = m_start;
8362 type = value_t::number_integer;
8363 max =
static_cast<uint64_t
>((std::numeric_limits<number_integer_t>::max)()) + 1;
8368 type = value_t::number_unsigned;
8369 max =
static_cast<uint64_t
>((std::numeric_limits<number_unsigned_t>::max)());
8373 for (; curptr < m_cursor; curptr++)
8376 if (*curptr < '0' || *curptr >
'9')
8381 type = value_t::number_float;
8386 type = value_t::number_float;
8391 if (type != value_t::number_float)
8394 auto temp = value * 10 + *curptr - 0x30;
8397 if (temp < value || temp > max)
8400 type = value_t::number_float;
8411 if (type == value_t::number_unsigned)
8413 result.m_value.number_unsigned = value;
8415 else if (type == value_t::number_integer)
8422 result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(
nullptr), NULL);
8426 result.m_type = type;
8431 std::istream* m_stream =
nullptr;
8435 const lexer_char_t* m_content =
nullptr;
8437 const lexer_char_t* m_start =
nullptr;
8439 const lexer_char_t* m_marker =
nullptr;
8441 const lexer_char_t* m_cursor =
nullptr;
8443 const lexer_char_t* m_limit =
nullptr;
8456 : callback(cb), m_lexer(s)
8464 : callback(cb), m_lexer(&_is)
8473 basic_json result = parse_internal(
true);
8475 expect(lexer::token_type::end_of_input);
8484 basic_json parse_internal(
bool keep)
8486 auto result = basic_json(value_t::discarded);
8490 case lexer::token_type::begin_object:
8492 if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
8495 result.m_type = value_t::object;
8496 result.m_value = json_value(value_t::object);
8503 if (last_token == lexer::token_type::end_object)
8506 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8508 result = basic_json(value_t::discarded);
8514 unexpect(lexer::token_type::value_separator);
8520 if (last_token == lexer::token_type::value_separator)
8526 expect(lexer::token_type::value_string);
8527 const auto key = m_lexer.get_string();
8529 bool keep_tag =
false;
8535 keep_tag = callback(depth, parse_event_t::key, k);
8545 expect(lexer::token_type::name_separator);
8549 auto value = parse_internal(keep);
8550 if (keep and keep_tag and not value.is_discarded())
8552 result[key] = std::move(value);
8555 while (last_token == lexer::token_type::value_separator);
8558 expect(lexer::token_type::end_object);
8560 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8562 result = basic_json(value_t::discarded);
8568 case lexer::token_type::begin_array:
8570 if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
8573 result.m_type = value_t::array;
8574 result.m_value = json_value(value_t::array);
8581 if (last_token == lexer::token_type::end_array)
8584 if (callback and not callback(--depth, parse_event_t::array_end, result))
8586 result = basic_json(value_t::discarded);
8592 unexpect(lexer::token_type::value_separator);
8598 if (last_token == lexer::token_type::value_separator)
8604 auto value = parse_internal(keep);
8605 if (keep and not value.is_discarded())
8607 result.push_back(std::move(value));
8610 while (last_token == lexer::token_type::value_separator);
8613 expect(lexer::token_type::end_array);
8615 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8617 result = basic_json(value_t::discarded);
8623 case lexer::token_type::literal_null:
8626 result.m_type = value_t::null;
8630 case lexer::token_type::value_string:
8632 const auto s = m_lexer.get_string();
8634 result = basic_json(s);
8638 case lexer::token_type::literal_true:
8641 result.m_type = value_t::boolean;
8642 result.m_value =
true;
8646 case lexer::token_type::literal_false:
8649 result.m_type = value_t::boolean;
8650 result.m_value =
false;
8654 case lexer::token_type::value_number:
8656 m_lexer.get_number(result);
8664 unexpect(last_token);
8668 if (keep and callback and not callback(depth, parse_event_t::value, result))
8670 result = basic_json(value_t::discarded);
8676 typename lexer::token_type get_token() noexcept
8678 last_token = m_lexer.scan();
8682 void expect(
typename lexer::token_type t)
const 8684 if (t != last_token)
8686 std::string error_msg =
"parse error - unexpected ";
8687 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token() +
"'") :
8688 lexer::token_type_name(last_token));
8689 error_msg +=
"; expected " + lexer::token_type_name(t);
8690 throw std::invalid_argument(error_msg);
8694 void unexpect(
typename lexer::token_type t)
const 8696 if (t == last_token)
8698 std::string error_msg =
"parse error - unexpected ";
8699 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token() +
"'") :
8700 lexer::token_type_name(last_token));
8701 throw std::invalid_argument(error_msg);
8711 typename lexer::token_type last_token = lexer::token_type::uninitialized;
8731 friend class basic_json;
8757 : reference_tokens(split(s))
8775 std::string to_string()
const noexcept
8779 for (
const auto& reference_token : reference_tokens)
8781 result +=
"/" + escape(reference_token);
8788 operator std::string()
const 8795 std::string pop_back()
8799 throw std::domain_error(
"JSON pointer has no parent");
8802 auto last = reference_tokens.back();
8803 reference_tokens.pop_back();
8808 bool is_root()
const 8810 return reference_tokens.empty();
8817 throw std::domain_error(
"JSON pointer has no parent");
8821 result.reference_tokens = {reference_tokens[0]};
8834 for (
const auto& reference_token : reference_tokens)
8836 switch (result->m_type)
8840 if (reference_token ==
"0")
8843 result = &result->operator[](0);
8848 result = &result->operator[](reference_token);
8853 case value_t::object:
8856 result = &result->operator[](reference_token);
8860 case value_t::array:
8863 result = &result->operator[](
static_cast<size_type>(std::stoi(reference_token)));
8876 throw std::domain_error(
"invalid value to unflatten");
8899 for (
const auto& reference_token : reference_tokens)
8901 switch (ptr->m_type)
8903 case value_t::object:
8906 ptr = &ptr->operator[](reference_token);
8910 case value_t::array:
8913 if (reference_token.size() > 1 and reference_token[0] ==
'0')
8915 throw std::domain_error(
"array index must not begin with '0'");
8918 if (reference_token ==
"-")
8921 ptr = &ptr->operator[](ptr->m_value.array->size());
8926 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
8933 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
8943 for (
const auto& reference_token : reference_tokens)
8945 switch (ptr->m_type)
8947 case value_t::object:
8950 ptr = &ptr->
at(reference_token);
8954 case value_t::array:
8956 if (reference_token ==
"-")
8959 throw std::out_of_range(
"array index '-' (" +
8960 std::to_string(ptr->m_value.array->size()) +
8961 ") is out of range");
8965 if (reference_token.size() > 1 and reference_token[0] ==
'0')
8967 throw std::domain_error(
"array index must not begin with '0'");
8971 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
8977 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
8995 for (
const auto& reference_token : reference_tokens)
8997 switch (ptr->m_type)
8999 case value_t::object:
9002 ptr = &ptr->operator[](reference_token);
9006 case value_t::array:
9008 if (reference_token ==
"-")
9011 throw std::out_of_range(
"array index '-' (" +
9012 std::to_string(ptr->m_value.array->size()) +
9013 ") is out of range");
9017 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9019 throw std::domain_error(
"array index must not begin with '0'");
9023 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9029 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9039 for (
const auto& reference_token : reference_tokens)
9041 switch (ptr->m_type)
9043 case value_t::object:
9046 ptr = &ptr->
at(reference_token);
9050 case value_t::array:
9052 if (reference_token ==
"-")
9055 throw std::out_of_range(
"array index '-' (" +
9056 std::to_string(ptr->m_value.array->size()) +
9057 ") is out of range");
9061 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9063 throw std::domain_error(
"array index must not begin with '0'");
9067 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9073 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9082 static std::vector<std::string> split(std::string reference_string)
9084 std::vector<std::string> result;
9087 if (reference_string.empty())
9093 if (reference_string[0] !=
'/')
9095 throw std::domain_error(
"JSON pointer must be empty or begin with '/'");
9103 size_t slash = reference_string.find_first_of(
"/", 1),
9112 slash = reference_string.find_first_of(
"/", start))
9116 auto reference_token = reference_string.substr(start, slash - start);
9119 for (
size_t pos = reference_token.find_first_of(
"~");
9120 pos != std::string::npos;
9121 pos = reference_token.find_first_of(
"~", pos + 1))
9123 assert(reference_token[pos] ==
'~');
9126 if (pos == reference_token.size() - 1 or
9127 (reference_token[pos + 1] !=
'0' and
9128 reference_token[pos + 1] !=
'1'))
9130 throw std::domain_error(
"escape error: '~' must be followed with '0' or '1'");
9135 unescape(reference_token);
9136 result.push_back(reference_token);
9157 static void replace_substring(std::string& s,
9158 const std::string& f,
9159 const std::string& t)
9161 assert(not f.empty());
9164 size_t pos = s.find(f);
9165 pos != std::string::npos;
9166 s.replace(pos, f.size(), t),
9167 pos = s.find(f, pos + t.size())
9172 static std::string escape(std::string s)
9175 replace_substring(s,
"~",
"~0");
9176 replace_substring(s,
"/",
"~1");
9181 static void unescape(std::string& s)
9184 replace_substring(s,
"~1",
"/");
9186 replace_substring(s,
"~0",
"~");
9196 static void flatten(
const std::string& reference_string,
9197 const basic_json& value,
9200 switch (value.m_type)
9202 case value_t::array:
9204 if (value.m_value.array->empty())
9207 result[reference_string] =
nullptr;
9212 for (
size_t i = 0; i < value.m_value.array->size(); ++i)
9214 flatten(reference_string +
"/" + std::to_string(i),
9215 value.m_value.array->operator[](i), result);
9221 case value_t::object:
9223 if (value.m_value.object->empty())
9226 result[reference_string] =
nullptr;
9231 for (
const auto& element : *value.m_value.object)
9233 flatten(reference_string +
"/" + escape(element.first),
9234 element.second, result);
9243 result[reference_string] = value;
9254 static basic_json unflatten(
const basic_json& value)
9258 throw std::domain_error(
"only objects can be unflattened");
9264 for (
const auto& element : *value.m_value.object)
9266 if (not element.second.is_primitive())
9268 throw std::domain_error(
"values in object must be primitive");
9276 json_pointer(element.first).get_and_create(result) = element.second;
9284 std::vector<std::string> reference_tokens {};
9329 return ptr.get_unchecked(
this);
9356 return ptr.get_unchecked(
this);
9381 return ptr.get_checked(
this);
9406 return ptr.get_checked(
this);
9431 basic_json flatten()
const 9433 basic_json result(value_t::object);
9434 json_pointer::flatten(
"", *
this, result);
9465 basic_json unflatten()
const 9467 return json_pointer::unflatten(*
this);
9515 basic_json patch(
const basic_json& json_patch)
const 9518 basic_json result = *
this;
9521 enum class patch_operations {add,
remove, replace, move, copy, test, invalid};
9523 const auto get_op = [](
const std::string op)
9527 return patch_operations::add;
9531 return patch_operations::remove;
9533 if (op ==
"replace")
9535 return patch_operations::replace;
9539 return patch_operations::move;
9543 return patch_operations::copy;
9547 return patch_operations::test;
9550 return patch_operations::invalid;
9554 const auto operation_add = [&result](
json_pointer & ptr, basic_json val)
9565 if (top_pointer != ptr)
9567 basic_json& x = result.
at(top_pointer);
9571 const auto last_path = ptr.pop_back();
9572 basic_json& parent = result[ptr];
9574 switch (parent.m_type)
9577 case value_t::object:
9580 parent[last_path] = val;
9584 case value_t::array:
9586 if (last_path ==
"-")
9593 const auto idx = std::stoi(last_path);
9594 if (static_cast<size_type>(idx) > parent.
size())
9597 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
9618 const auto operation_remove = [&result](
json_pointer & ptr)
9621 const auto last_path = ptr.pop_back();
9622 basic_json& parent = result.
at(ptr);
9628 auto it = parent.
find(last_path);
9629 if (it != parent.
end())
9635 throw std::out_of_range(
"key '" + last_path +
"' not found");
9641 parent.
erase(static_cast<size_type>(std::stoi(last_path)));
9649 throw std::invalid_argument(
"JSON patch must be an array of objects");
9653 for (
const auto& val : json_patch)
9656 const auto get_value = [&val](
const std::string & op,
9657 const std::string & member,
9658 bool string_type) -> basic_json&
9661 auto it = val.m_value.object->find(member);
9664 const auto error_msg = (op ==
"op") ?
"operation" :
"operation '" + op +
"'";
9667 if (it == val.m_value.object->end())
9669 throw std::invalid_argument(error_msg +
" must have member '" + member +
"'");
9673 if (string_type and not it->second.is_string())
9675 throw std::invalid_argument(error_msg +
" must have string member '" + member +
"'");
9683 if (not val.is_object())
9685 throw std::invalid_argument(
"JSON patch must be an array of objects");
9689 const std::string op = get_value(
"op",
"op",
true);
9690 const std::string path = get_value(op,
"path",
true);
9695 case patch_operations::add:
9697 operation_add(ptr, get_value(
"add",
"value",
false));
9701 case patch_operations::remove:
9703 operation_remove(ptr);
9707 case patch_operations::replace:
9710 result.
at(ptr) = get_value(
"replace",
"value",
false);
9714 case patch_operations::move:
9716 const std::string from_path = get_value(
"move",
"from",
true);
9720 basic_json v = result.
at(from_ptr);
9726 operation_remove(from_ptr);
9727 operation_add(ptr, v);
9731 case patch_operations::copy:
9733 const std::string from_path = get_value(
"copy",
"from",
true);;
9737 result[ptr] = result.
at(from_ptr);
9741 case patch_operations::test:
9743 bool success =
false;
9748 success = (result.
at(ptr) == get_value(
"test",
"value",
false));
9750 catch (std::out_of_range&)
9758 throw std::domain_error(
"unsuccessful: " + val.dump());
9764 case patch_operations::invalid:
9768 throw std::invalid_argument(
"operation value '" + op +
"' is invalid");
9808 static basic_json diff(
const basic_json& source,
9809 const basic_json& target,
9810 std::string path =
"")
9813 basic_json result(value_t::array);
9816 if (source == target)
9821 if (source.
type() != target.
type())
9833 switch (source.
type())
9835 case value_t::array:
9839 while (i < source.
size() and i < target.
size())
9842 auto temp_diff = diff(source[i], target[i], path +
"/" + std::to_string(i));
9843 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
9852 while (i < source.
size())
9856 result.insert(result.begin() + end_index, object(
9859 {
"path", path +
"/" + std::to_string(i)}
9865 while (i < target.
size())
9870 {
"path", path +
"/" + std::to_string(i)},
9871 {
"value", target[i]}
9879 case value_t::object:
9882 for (
auto it = source.
begin(); it != source.
end(); ++it)
9885 const auto key = json_pointer::escape(it.key());
9887 if (target.
find(it.key()) != target.
end())
9890 auto temp_diff = diff(it.value(), target[it.key()], path +
"/" + key);
9891 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
9896 result.push_back(
object(
9899 {
"path", path +
"/" + key}
9905 for (
auto it = target.
begin(); it != target.
end(); ++it)
9907 if (source.
find(it.key()) == source.
end())
9910 const auto key = json_pointer::escape(it.key());
9914 {
"path", path +
"/" + key},
9915 {
"value", it.value()}
9975 is_nothrow_move_constructible<nlohmann::json>::value and
9976 is_nothrow_move_assignable<nlohmann::json>::value
9994 const auto& h = hash<nlohmann::json::string_t>();
10012 inline nlohmann::json operator "" _json(
const char* s, std::size_t)
10028 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 10029 #pragma GCC diagnostic pop const_iterator(pointer object) noexcept
constructor for a given JSON instance
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
basic_json(const value_t value_type)
create an empty value with a given type
basic_json(const array_t &val)
create an array (explicit)
size_type count(typename object_t::key_type key) const
returns the number of occurrences of a key in a JSON object
const_reference operator[](size_type idx) const
access specified array element
reference value() const
return the value of an iterator
json_reverse_iterator & operator--()
pre-decrement (–it)
void clear() noexcept
clears the contents
bool operator==(const const_iterator &other) const
comparison: equal
json_reverse_iterator operator--(int)
post-decrement (it–)
reference operator[](T *(&key)[n])
access specified object element
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
iterator & operator+=(difference_type i)
add to iterator
static basic_json object(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an object from an initializer list
const_iterator operator-(difference_type i)
subtract from iterator
BooleanType boolean_t
a type for a boolean
const_iterator cbegin() const noexcept
returns a const iterator to the first element
reference operator+=(const typename object_t::value_type &val)
add an object to an object
reference operator*() const
return a reference to the value pointed to by the iterator
basic_json(const typename string_t::value_type *val)
create a string (explicit)
reference operator[](difference_type n) const
access to successor
iterator find(typename object_t::key_type key)
find an element in a JSON object
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
basic_json(const string_t &val)
create a string (explicit)
void push_back(const basic_json &val)
add an object to an array
void erase(const size_type idx)
remove element from a JSON array given an index
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
reference front()
access the first element
void swap(object_t &other)
exchanges the values
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
const_iterator & operator+=(difference_type i)
add to iterator
a class to store JSON values
basic_json(const int val) noexcept
create an integer number from an enum type (explicit)
reference value() const
return the value of an iterator
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
NumberIntegerType number_integer_t
a type for a number (integer)
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
const_iterator operator+(difference_type i)
add to iterator
constexpr bool is_object() const noexcept
return whether value is an object
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
a mutable random access iterator for the basic_json class
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
const_iterator operator++(int)
post-increment (it++)
const_iterator cend() const noexcept
returns a const iterator to one past the last element
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
basic_json(const number_integer_t val) noexcept
create an integer number (explicit)
static basic_json array(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an array from an initializer list
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
reference & operator=(basic_json other) noexcept( std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value )
copy assignment
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
PointerType get_ptr() noexcept
get a pointer value (implicit)
constexpr bool is_string() const noexcept
return whether value is a string
reference back()
access the last element
const value_type & const_reference
the type of an element const reference
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
void push_back(const typename object_t::value_type &val)
add an object to an object
void push_back(std::initializer_list< basic_json > init)
add an object to an object
json_pointer(const std::string &s="")
create JSON pointer
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
basic_json(std::nullptr_t) noexcept
create a null object (explicitly)
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
reference operator[](difference_type n) const
access to successor
static allocator_type get_allocator()
returns the allocator associated with the container
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
const_reference operator[](T *key) const
read-only access specified object element
json_reverse_iterator operator+(difference_type i) const
add to iterator
bool empty() const noexcept
checks whether the container is empty
std::size_t size_type
a type to represent container sizes
object_t::key_type key() const
return the key of an object iterator
const_iterator(const iterator &other) noexcept
copy constructor given a nonconst iterator
basic_json(const CompatibleArrayType &val)
create an array (implicit)
constexpr bool is_boolean() const noexcept
return whether value is a boolean
const_reference at(size_type idx) const
access specified array element with bounds checking
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
iterator insert(const_iterator pos, const basic_json &val)
inserts element
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
iterator & operator++()
pre-increment (++it)
bool operator<(const const_iterator &other) const
comparison: smaller
iterator operator++(int)
post-increment (it++)
basic_json(basic_json &&other) noexcept
move constructor
const_iterator operator--(int)
post-decrement (it–)
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
iterator & operator=(iterator other) noexcept( std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value )
copy assignment
object (unordered set of name/value pairs)
size_type max_size() const noexcept
returns the maximum possible number of elements
iterator operator--(int)
post-decrement (it–)
iterator operator-(difference_type i)
subtract from iterator
const_iterator & operator--()
pre-decrement (–it)
string_t dump(const int indent=-1) const
serialization
basic_json value_type
the type of elements in a basic_json container
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
AllocatorType< basic_json > allocator_type
the allocator type
StringType string_t
a type for a string
reference operator+=(const basic_json &val)
add an object to an array
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
difference_type operator-(const const_iterator &other) const
return difference
value_type & reference
the type of an element reference
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
constexpr bool is_discarded() const noexcept
return whether value is discarded
const_iterator begin() const noexcept
returns a const iterator to the first element
difference_type operator-(const iterator &other) const
return difference
constexpr bool is_array() const noexcept
return whether value is an array
iterator(const iterator &other) noexcept
copy constructor
namespace for Niels Lohmann
typename basic_json::difference_type difference_type
a type to represent differences between iterators
void swap(string_t &other)
exchanges the values
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
const_reference front() const
access the first element
bool operator>(const const_iterator &other) const
comparison: greater than
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
pointer operator->() const
dereference the iterator
NumberFloatType number_float_t
a type for a number (floating-point)
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
void swap(reference other) noexcept( std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value )
exchanges the values
value_t
the JSON type enumeration
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
constexpr bool is_null() const noexcept
return whether value is null
std::ptrdiff_t difference_type
a type to represent differences between iterators
ValueType get() const
get a value (explicit)
void swap(array_t &other)
exchanges the values
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
typename Base::reference reference
the reference type for the pointed-to element
const_reference back() const
access the last element
void push_back(basic_json &&val)
add an object to an array
array (ordered collection of values)
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
json_reverse_iterator & operator++()
pre-increment (++it)
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
string_t value(const typename object_t::key_type &key, const char *default_value) const
overload for a default value of type const char*
ReferenceType get_ref() const
get a reference value (implicit)
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
reference operator*() const
return a reference to the value pointed to by the iterator
friend bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
basic_json(const number_float_t val) noexcept
create a floating-point number (explicit)
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
iterator operator+(difference_type i)
add to iterator
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
bool operator<=(const const_iterator &other) const
comparison: less than or equal
InteratorType erase(InteratorType pos)
remove element given an iterator
basic_json(std::initializer_list< basic_json > init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
iterator(pointer object) noexcept
constructor for a given JSON instance
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
constexpr bool is_primitive() const noexcept
return whether type is primitive
const_iterator & operator++()
pre-increment (++it)
pointer operator->() const
dereference the iterator
reference value() const
return the value of an iterator
constexpr bool is_structured() const noexcept
return whether type is structured
std::bidirectional_iterator_tag iterator_category
the category of the iterator
basic_json(boolean_t val) noexcept
create a boolean (explicit)
iterator end() noexcept
returns an iterator to one past the last element
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
difference_type operator-(const json_reverse_iterator &other) const
return difference
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
iterator begin() noexcept
returns an iterator to the first element
basic_json(const CompatibleObjectType &val)
create an object (implicit)
const_iterator end() const noexcept
returns a const iterator to one past the last element
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
const_iterator & operator=(const_iterator other) noexcept( std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value )
copy assignment
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
reference operator[](const typename object_t::key_type &key)
access specified object element
object_t::key_type key() const
return the key of an object iterator
reference operator+=(basic_json &&val)
add an object to an array
reference operator[](difference_type n) const
access to successor
a const random access iterator for the basic_json class
constexpr bool is_number() const noexcept
return whether value is a number
a template for a reverse iterator class
basic_json(std::istream &i, parser_callback_t cb=nullptr)
construct a JSON value given an input stream
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
json_reverse_iterator operator++(int)
post-increment (it++)
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
reference operator[](size_type idx)
access specified array element
bool operator!=(const const_iterator &other) const
comparison: not equal
json_reverse_iterator & operator+=(difference_type i)
add to iterator
reference at(size_type idx)
access specified array element with bounds checking
size_type size() const noexcept
returns the number of elements
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
iterator & operator-=(difference_type i)
subtract from iterator
basic_json(const object_t &val)
create an object (explicit)
basic_json(const number_unsigned_t val) noexcept
create an unsigned integer number (explicit)
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
const_iterator(const const_iterator &other) noexcept
copy constructor
iterator & operator--()
pre-decrement (–it)
iterator insert(const_iterator pos, basic_json &&val)
inserts element
ReferenceType get_ref()
get a reference value (implicit)
const_iterator & operator-=(difference_type i)
subtract from iterator
basic_json(const CompatibleStringType &val)
create a string (implicit)
basic_json(const basic_json &other)
copy constructor
reference operator[](T *key)
access specified object element
parse_event_t
JSON callback events.