29 #ifndef NLOHMANN_JSON_HPP 30 #define NLOHMANN_JSON_HPP 43 #include <initializer_list> 55 #include <type_traits> 60 #if defined(__clang__) 61 #define CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) 62 #if CLANG_VERSION < 30400 63 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" 65 #elif defined(__GNUC__) 66 #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) 67 #if GCC_VERSION < 40900 68 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" 73 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 74 #pragma GCC diagnostic push 75 #pragma GCC diagnostic ignored "-Wfloat-equal" 79 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 80 #define JSON_DEPRECATED __attribute__((deprecated)) 81 #elif defined(_MSC_VER) 82 #define JSON_DEPRECATED __declspec(deprecated) 84 #define JSON_DEPRECATED 113 struct has_mapped_type
116 template <
typename U,
typename =
typename U::mapped_type>
117 static int detect(U&&);
119 static void detect(...);
121 static constexpr
bool value =
122 std::is_integral<decltype(detect(std::declval<T>()))>::value;
137 struct DecimalSeparator : std::numpunct<char>
139 char do_decimal_point()
const 226 template<
typename U,
typename V,
typename... Args>
class ObjectType = std::map,
227 template<
typename U,
typename... Args>
class ArrayType = std::vector,
228 class StringType = std::string,
229 class BooleanType = bool,
230 class NumberIntegerType = std::int64_t,
231 class NumberUnsignedType = std::uint64_t,
232 class NumberFloatType = double,
233 template<
typename U>
class AllocatorType = std::allocator
240 BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,
274 using pointer =
typename std::allocator_traits<allocator_type>::pointer;
276 using const_pointer =
typename std::allocator_traits<allocator_type>::const_pointer;
391 using object_t = ObjectType<StringType,
393 std::less<StringType>,
394 AllocatorType<std::pair<
const StringType,
441 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
773 template<
typename T,
typename... Args>
774 static T* create(Args&& ... args)
776 AllocatorType<T> alloc;
777 auto deleter = [&](T * object)
779 alloc.deallocate(
object, 1);
781 std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
782 alloc.construct(
object.
get(), std::forward<Args>(args)...);
783 assert(
object.
get() !=
nullptr);
784 return object.release();
833 json_value() =
default;
835 json_value(
boolean_t v) noexcept : boolean(v) {}
847 case value_t::object:
849 object = create<object_t>();
855 array = create<array_t>();
859 case value_t::string:
861 string = create<string_t>(
"");
865 case value_t::boolean:
871 case value_t::number_integer:
877 case value_t::number_unsigned:
883 case value_t::number_float:
899 string = create<string_t>(value);
905 object = create<object_t>(value);
909 json_value(
const array_t& value)
911 array = create<array_t>(value);
924 void assert_invariant()
const 926 assert(m_type != value_t::object or m_value.object !=
nullptr);
927 assert(m_type != value_t::array or m_value.array !=
nullptr);
928 assert(m_type != value_t::string or m_value.string !=
nullptr);
1016 basic_json& parsed)>;
1068 : m_type(value_type), m_value(value_type)
1117 : m_type(
value_t::object), m_value(val)
1148 template<
class CompatibleObjectType,
typename std::enable_if<
1149 std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1150 std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value,
int>::type = 0>
1156 m_value.object = create<object_t>(begin(val), end(val));
1180 : m_type(
value_t::array), m_value(val)
1211 template<
class CompatibleArrayType,
typename std::enable_if<
1212 not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1213 not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1214 not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1215 not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1216 not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1217 not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1218 std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value,
int>::type = 0>
1224 m_value.array = create<array_t>(begin(val), end(val));
1250 : m_type(
value_t::string), m_value(val)
1304 template<
class CompatibleStringType,
typename std::enable_if<
1305 std::is_constructible<string_t, CompatibleStringType>::value,
int>::type = 0>
1327 : m_type(value_t::boolean), m_value(val)
1355 template<
typename T,
typename std::enable_if<
1356 not (std::is_same<T, int>::value) and
1357 std::is_same<T, number_integer_t>::value,
int>::type = 0>
1359 : m_type(value_t::number_integer), m_value(val)
1390 : m_type(value_t::number_integer),
1391 m_value(static_cast<number_integer_t>(val))
1421 template<
typename CompatibleNumberIntegerType,
typename std::enable_if<
1422 std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1423 std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1424 std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1425 CompatibleNumberIntegerType>::type = 0>
1427 : m_type(value_t::number_integer),
1428 m_value(static_cast<number_integer_t>(val))
1450 template<
typename T,
typename std::enable_if<
1451 not (std::is_same<T, int>::value) and
1452 std::is_same<T, number_unsigned_t>::value,
int>::type = 0>
1454 : m_type(value_t::number_unsigned), m_value(val)
1479 template<
typename CompatibleNumberUnsignedType,
typename std::enable_if <
1480 std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1481 std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1482 not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1483 CompatibleNumberUnsignedType>::type = 0>
1485 : m_type(value_t::number_unsigned),
1486 m_value(static_cast<number_unsigned_t>(val))
1516 : m_type(value_t::number_float), m_value(val)
1519 if (not std::isfinite(val))
1521 m_type = value_t::null;
1522 m_value = json_value();
1559 template<
typename CompatibleNumberFloatType,
typename =
typename std::enable_if<
1560 std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1561 std::is_floating_point<CompatibleNumberFloatType>::value>::type>
1638 bool type_deduction =
true,
1639 value_t manual_type = value_t::array)
1643 bool is_an_object = std::all_of(init.begin(), init.end(),
1646 return element.is_array() and element.size() == 2 and element[0].is_string();
1650 if (not type_deduction)
1653 if (manual_type == value_t::array)
1655 is_an_object =
false;
1659 if (manual_type == value_t::object and not is_an_object)
1661 throw std::domain_error(
"cannot create object from initializer list");
1668 m_type = value_t::object;
1669 m_value = value_t::object;
1671 std::for_each(init.begin(), init.end(), [
this](
const basic_json & element)
1673 m_value.object->emplace(*(element[0].m_value.string), element[1]);
1679 m_type = value_t::array;
1680 m_value.array = create<array_t>(init);
1721 std::initializer_list<basic_json>())
1723 return basic_json(init,
false, value_t::array);
1761 std::initializer_list<basic_json>())
1763 return basic_json(init,
false, value_t::object);
1787 m_value.array = create<array_t>(cnt, val);
1828 template<
class InputIT,
typename std::enable_if<
1829 std::is_same<InputIT, typename basic_json_t::iterator>::value or
1830 std::is_same<InputIT, typename basic_json_t::const_iterator>::value,
int>::type = 0>
1833 assert(first.m_object !=
nullptr);
1834 assert(last.m_object !=
nullptr);
1837 if (first.m_object != last.m_object)
1839 throw std::domain_error(
"iterators are not compatible");
1843 m_type = first.m_object->m_type;
1848 case value_t::boolean:
1849 case value_t::number_float:
1850 case value_t::number_integer:
1851 case value_t::number_unsigned:
1852 case value_t::string:
1854 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1856 throw std::out_of_range(
"iterators out of range");
1869 case value_t::number_integer:
1871 m_value.number_integer = first.m_object->m_value.number_integer;
1875 case value_t::number_unsigned:
1877 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1881 case value_t::number_float:
1883 m_value.number_float = first.m_object->m_value.number_float;
1887 case value_t::boolean:
1889 m_value.boolean = first.m_object->m_value.boolean;
1893 case value_t::string:
1895 m_value = *first.m_object->m_value.string;
1899 case value_t::object:
1901 m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1905 case value_t::array:
1907 m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1913 throw std::domain_error(
"cannot use construct with iterators from " + first.m_object->type_name());
1951 *
this = parser(i, cb).parse();
1982 : m_type(other.m_type)
1985 other.assert_invariant();
1989 case value_t::object:
1991 m_value = *other.m_value.object;
1995 case value_t::array:
1997 m_value = *other.m_value.array;
2001 case value_t::string:
2003 m_value = *other.m_value.string;
2007 case value_t::boolean:
2009 m_value = other.m_value.boolean;
2013 case value_t::number_integer:
2015 m_value = other.m_value.number_integer;
2019 case value_t::number_unsigned:
2021 m_value = other.m_value.number_unsigned;
2025 case value_t::number_float:
2027 m_value = other.m_value.number_float;
2059 : m_type(
std::move(other.m_type)),
2060 m_value(
std::move(other.m_value))
2063 other.assert_invariant();
2066 other.m_type = value_t::null;
2096 std::is_nothrow_move_constructible<value_t>::value and
2097 std::is_nothrow_move_assignable<value_t>::value and
2098 std::is_nothrow_move_constructible<json_value>::value and
2099 std::is_nothrow_move_assignable<json_value>::value
2103 other.assert_invariant();
2106 swap(m_type, other.m_type);
2107 swap(m_value, other.m_value);
2134 case value_t::object:
2136 AllocatorType<object_t> alloc;
2137 alloc.destroy(m_value.object);
2138 alloc.deallocate(m_value.object, 1);
2142 case value_t::array:
2144 AllocatorType<array_t> alloc;
2145 alloc.destroy(m_value.array);
2146 alloc.deallocate(m_value.array, 1);
2150 case value_t::string:
2152 AllocatorType<string_t> alloc;
2153 alloc.destroy(m_value.string);
2154 alloc.deallocate(m_value.string, 1);
2202 std::stringstream ss;
2204 const static std::locale loc(std::locale(),
new DecimalSeparator);
2211 ss.precision(std::numeric_limits<double>::digits10);
2215 dump(ss,
true, static_cast<unsigned int>(indent));
2275 return is_null() or is_string() or is_boolean() or is_number();
2302 return is_array() or is_object();
2324 return m_type == value_t::null;
2346 return m_type == value_t::boolean;
2376 return is_number_integer() or is_number_float();
2405 return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2433 return m_type == value_t::number_unsigned;
2461 return m_type == value_t::number_float;
2483 return m_type == value_t::object;
2505 return m_type == value_t::array;
2527 return m_type == value_t::string;
2554 return m_type == value_t::discarded;
2588 template<
class T,
typename std::enable_if<
2589 std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2590 std::is_convertible<basic_json_t, typename T::mapped_type>::value,
int>::type = 0>
2591 T get_impl(T*)
const 2595 return T(m_value.object->begin(), m_value.object->end());
2599 throw std::domain_error(
"type must be object, but is " + type_name());
2608 return *(m_value.object);
2612 throw std::domain_error(
"type must be object, but is " + type_name());
2617 template<
class T,
typename std::enable_if<
2618 std::is_convertible<basic_json_t, typename T::value_type>::value and
2619 not std::is_same<basic_json_t, typename T::value_type>::value and
2620 not std::is_arithmetic<T>::value and
2621 not std::is_convertible<std::string, T>::value and
2622 not has_mapped_type<T>::value,
int>::type = 0>
2623 T get_impl(T*)
const 2628 std::transform(m_value.array->begin(), m_value.array->end(),
2629 std::inserter(to_vector, to_vector.end()), [](
basic_json i)
2631 return i.
get<
typename T::value_type>();
2637 throw std::domain_error(
"type must be array, but is " + type_name());
2642 template<
class T,
typename std::enable_if<
2643 std::is_convertible<basic_json_t, T>::value and
2644 not std::is_same<basic_json_t, T>::value,
int>::type = 0>
2645 std::vector<T> get_impl(std::vector<T>*)
const 2649 std::vector<T> to_vector;
2650 to_vector.reserve(m_value.array->size());
2651 std::transform(m_value.array->begin(), m_value.array->end(),
2652 std::inserter(to_vector, to_vector.end()), [](
basic_json i)
2660 throw std::domain_error(
"type must be array, but is " + type_name());
2665 template<
class T,
typename std::enable_if<
2666 std::is_same<basic_json, typename T::value_type>::value and
2667 not has_mapped_type<T>::value,
int>::type = 0>
2668 T get_impl(T*)
const 2672 return T(m_value.array->begin(), m_value.array->end());
2676 throw std::domain_error(
"type must be array, but is " + type_name());
2685 return *(m_value.array);
2689 throw std::domain_error(
"type must be array, but is " + type_name());
2694 template<
typename T,
typename std::enable_if<
2695 std::is_convertible<string_t, T>::value,
int>::type = 0>
2696 T get_impl(T*)
const 2700 return *m_value.string;
2704 throw std::domain_error(
"type must be string, but is " + type_name());
2709 template<
typename T,
typename std::enable_if<
2710 std::is_arithmetic<T>::value,
int>::type = 0>
2711 T get_impl(T*)
const 2715 case value_t::number_integer:
2717 return static_cast<T
>(m_value.number_integer);
2720 case value_t::number_unsigned:
2722 return static_cast<T
>(m_value.number_unsigned);
2725 case value_t::number_float:
2727 return static_cast<T
>(m_value.number_float);
2732 throw std::domain_error(
"type must be number, but is " + type_name());
2742 :
throw std::domain_error(
"type must be boolean, but is " + type_name());
2748 return is_object() ? m_value.object :
nullptr;
2754 return is_object() ? m_value.object :
nullptr;
2760 return is_array() ? m_value.array :
nullptr;
2764 constexpr
const array_t* get_impl_ptr(
const array_t*)
const noexcept
2766 return is_array() ? m_value.array :
nullptr;
2772 return is_string() ? m_value.string :
nullptr;
2778 return is_string() ? m_value.string :
nullptr;
2784 return is_boolean() ? &m_value.boolean :
nullptr;
2790 return is_boolean() ? &m_value.boolean :
nullptr;
2796 return is_number_integer() ? &m_value.number_integer :
nullptr;
2802 return is_number_integer() ? &m_value.number_integer :
nullptr;
2808 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2814 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2820 return is_number_float() ? &m_value.number_float :
nullptr;
2826 return is_number_float() ? &m_value.number_float :
nullptr;
2840 template<
typename ReferenceType,
typename ThisType>
2841 static ReferenceType get_ref_impl(ThisType& obj)
2844 using PointerType =
typename std::add_pointer<ReferenceType>::type;
2847 auto ptr = obj.template get_ptr<PointerType>();
2855 throw std::domain_error(
"incompatible ReferenceType for get_ref, actual type is " +
2899 template<
typename ValueType,
typename std::enable_if<
2900 not std::is_pointer<ValueType>::value,
int>::type = 0>
2901 ValueType
get()
const 2903 return get_impl(static_cast<ValueType*>(
nullptr));
2933 template<
typename PointerType,
typename std::enable_if<
2934 std::is_pointer<PointerType>::value,
int>::type = 0>
2935 PointerType
get() noexcept
2938 return get_ptr<PointerType>();
2945 template<
typename PointerType,
typename std::enable_if<
2946 std::is_pointer<PointerType>::value,
int>::type = 0>
2947 constexpr
const PointerType
get()
const noexcept
2950 return get_ptr<PointerType>();
2979 template<
typename PointerType,
typename std::enable_if<
2980 std::is_pointer<PointerType>::value,
int>::type = 0>
2984 using pointee_t =
typename std::remove_const<
typename 2985 std::remove_pointer<
typename 2986 std::remove_const<PointerType>::type>::type>::type;
2989 std::is_same<object_t, pointee_t>::value
2990 or std::is_same<array_t, pointee_t>::value
2991 or std::is_same<string_t, pointee_t>::value
2992 or std::is_same<boolean_t, pointee_t>::value
2993 or std::is_same<number_integer_t, pointee_t>::value
2994 or std::is_same<number_unsigned_t, pointee_t>::value
2995 or std::is_same<number_float_t, pointee_t>::value
2996 ,
"incompatible pointer type");
2999 return get_impl_ptr(static_cast<PointerType>(
nullptr));
3006 template<
typename PointerType,
typename std::enable_if<
3007 std::is_pointer<PointerType>::value and
3008 std::is_const<typename std::remove_pointer<PointerType>::type>::value,
int>::type = 0>
3009 constexpr
const PointerType
get_ptr() const noexcept
3012 using pointee_t =
typename std::remove_const<
typename 3013 std::remove_pointer<
typename 3014 std::remove_const<PointerType>::type>::type>::type;
3017 std::is_same<object_t, pointee_t>::value
3018 or std::is_same<array_t, pointee_t>::value
3019 or std::is_same<string_t, pointee_t>::value
3020 or std::is_same<boolean_t, pointee_t>::value
3021 or std::is_same<number_integer_t, pointee_t>::value
3022 or std::is_same<number_unsigned_t, pointee_t>::value
3023 or std::is_same<number_float_t, pointee_t>::value
3024 ,
"incompatible pointer type");
3027 return get_impl_ptr(static_cast<const PointerType>(
nullptr));
3056 template<
typename ReferenceType,
typename std::enable_if<
3057 std::is_reference<ReferenceType>::value,
int>::type = 0>
3061 return get_ref_impl<ReferenceType>(*this);
3068 template<
typename ReferenceType,
typename std::enable_if<
3069 std::is_reference<ReferenceType>::value and
3070 std::is_const<typename std::remove_reference<ReferenceType>::type>::value,
int>::type = 0>
3074 return get_ref_impl<ReferenceType>(*this);
3105 template <
typename ValueType,
typename std::enable_if <
3106 not std::is_pointer<ValueType>::value and
3107 not std::is_same<ValueType, typename string_t::value_type>::value
3108 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015 3109 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3112 operator ValueType()
const 3115 return get<ValueType>();
3158 return m_value.
array->
at(idx);
3160 catch (std::out_of_range&)
3163 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3168 throw std::domain_error(
"cannot use at() with " + type_name());
3201 return m_value.
array->
at(idx);
3203 catch (std::out_of_range&)
3206 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3211 throw std::domain_error(
"cannot use at() with " + type_name());
3250 catch (std::out_of_range&)
3253 throw std::out_of_range(
"key '" + key +
"' not found");
3258 throw std::domain_error(
"cannot use at() with " + type_name());
3297 catch (std::out_of_range&)
3300 throw std::out_of_range(
"key '" + key +
"' not found");
3305 throw std::domain_error(
"cannot use at() with " + type_name());
3339 m_type = value_t::array;
3340 m_value.
array = create<array_t>();
3348 if (idx >= m_value.array->size())
3350 m_value.array->insert(m_value.array->end(),
3351 idx - m_value.array->size() + 1,
3355 return m_value.array->operator[](idx);
3359 throw std::domain_error(
"cannot use operator[] with " + type_name());
3387 return m_value.
array->operator[](idx);
3391 throw std::domain_error(
"cannot use operator[] with " + type_name());
3427 m_type = value_t::object;
3428 m_value.
object = create<object_t>();
3435 return m_value.object->operator[](key);
3439 throw std::domain_error(
"cannot use operator[] with " + type_name());
3478 assert(m_value.object->find(key) != m_value.object->end());
3483 throw std::domain_error(
"cannot use operator[] with " + type_name());
3514 template<
typename T, std::
size_t n>
3517 return operator[](static_cast<const T>(key));
3549 template<
typename T, std::
size_t n>
3552 return operator[](static_cast<const T>(key));
3582 template<
typename T>
3588 m_type = value_t::object;
3589 m_value = value_t::object;
3596 return m_value.object->operator[](key);
3600 throw std::domain_error(
"cannot use operator[] with " + type_name());
3634 template<
typename T>
3640 assert(m_value.object->find(key) != m_value.object->end());
3645 throw std::domain_error(
"cannot use operator[] with " + type_name());
3697 template<
class ValueType,
typename std::enable_if<
3698 std::is_convertible<basic_json_t, ValueType>::value,
int>::type = 0>
3699 ValueType
value(
const typename object_t::key_type& key, ValueType default_value)
const 3705 const auto it = find(key);
3712 return default_value;
3717 throw std::domain_error(
"cannot use value() with " + type_name());
3725 string_t value(
const typename object_t::key_type& key,
const char* default_value)
const 3727 return value(key,
string_t(default_value));
3771 template<
class ValueType,
typename std::enable_if<
3772 std::is_convertible<basic_json_t, ValueType>::value,
int>::type = 0>
3781 return ptr.get_checked(
this);
3783 catch (std::out_of_range&)
3785 return default_value;
3790 throw std::domain_error(
"cannot use value() with " + type_name());
3800 return value(ptr,
string_t(default_value));
3933 template<
class IteratorType,
typename std::enable_if<
3934 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
3935 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int>::type
3940 if (
this != pos.m_object)
3942 throw std::domain_error(
"iterator does not fit current value");
3945 IteratorType result = end();
3949 case value_t::boolean:
3950 case value_t::number_float:
3951 case value_t::number_integer:
3952 case value_t::number_unsigned:
3953 case value_t::string:
3955 if (not pos.m_it.primitive_iterator.is_begin())
3957 throw std::out_of_range(
"iterator out of range");
3962 AllocatorType<string_t> alloc;
3963 alloc.destroy(m_value.string);
3964 alloc.deallocate(m_value.string, 1);
3965 m_value.string =
nullptr;
3968 m_type = value_t::null;
3973 case value_t::object:
3975 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3979 case value_t::array:
3981 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3987 throw std::domain_error(
"cannot use erase() with " + type_name());
4040 template<
class IteratorType,
typename std::enable_if<
4041 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4042 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int>::type
4044 IteratorType
erase(IteratorType first, IteratorType last)
4047 if (
this != first.m_object or
this != last.m_object)
4049 throw std::domain_error(
"iterators do not fit current value");
4052 IteratorType result = end();
4056 case value_t::boolean:
4057 case value_t::number_float:
4058 case value_t::number_integer:
4059 case value_t::number_unsigned:
4060 case value_t::string:
4062 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
4064 throw std::out_of_range(
"iterators out of range");
4069 AllocatorType<string_t> alloc;
4070 alloc.destroy(m_value.string);
4071 alloc.deallocate(m_value.string, 1);
4072 m_value.string =
nullptr;
4075 m_type = value_t::null;
4080 case value_t::object:
4082 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4083 last.m_it.object_iterator);
4087 case value_t::array:
4089 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4090 last.m_it.array_iterator);
4096 throw std::domain_error(
"cannot use erase() with " + type_name());
4137 return m_value.object->erase(key);
4141 throw std::domain_error(
"cannot use erase() with " + type_name());
4176 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
4179 m_value.array->erase(m_value.array->begin() +
static_cast<difference_type>(idx));
4183 throw std::domain_error(
"cannot use erase() with " + type_name());
4217 auto result = end();
4221 result.m_it.object_iterator = m_value.object->find(key);
4233 auto result = cend();
4237 result.m_it.object_iterator = m_value.object->find(key);
4264 return is_object() ? m_value.object->count(key) : 0;
4552 template<
typename IteratorType>
class iteration_proxy;
4568 return iteration_proxy<iterator>(cont);
4576 return iteration_proxy<const_iterator>(cont);
4636 case value_t::array:
4639 return m_value.array->empty();
4642 case value_t::object:
4645 return m_value.object->empty();
4704 case value_t::array:
4707 return m_value.array->size();
4710 case value_t::object:
4713 return m_value.object->size();
4764 case value_t::array:
4767 return m_value.array->max_size();
4770 case value_t::object:
4773 return m_value.object->max_size();
4823 case value_t::number_integer:
4825 m_value.number_integer = 0;
4829 case value_t::number_unsigned:
4831 m_value.number_unsigned = 0;
4835 case value_t::number_float:
4837 m_value.number_float = 0.0;
4841 case value_t::boolean:
4843 m_value.boolean =
false;
4847 case value_t::string:
4849 m_value.string->clear();
4853 case value_t::array:
4855 m_value.array->clear();
4859 case value_t::object:
4861 m_value.object->clear();
4895 if (not(is_null() or is_array()))
4897 throw std::domain_error(
"cannot use push_back() with " + type_name());
4903 m_type = value_t::array;
4904 m_value = value_t::array;
4909 m_value.array->push_back(std::move(val));
4911 val.m_type = value_t::null;
4920 push_back(std::move(val));
4931 if (not(is_null() or is_array()))
4933 throw std::domain_error(
"cannot use push_back() with " + type_name());
4939 m_type = value_t::array;
4940 m_value = value_t::array;
4945 m_value.array->push_back(val);
4981 if (not(is_null() or is_object()))
4983 throw std::domain_error(
"cannot use push_back() with " + type_name());
4989 m_type = value_t::object;
4990 m_value = value_t::object;
4995 m_value.object->insert(val);
5035 if (is_object() and init.size() == 2 and init.begin()->is_string())
5037 const string_t key = *init.begin();
5038 push_back(
typename object_t::value_type(key, *(init.begin() + 1)));
5084 if (pos.m_object !=
this)
5086 throw std::domain_error(
"iterator does not fit current value");
5091 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
5096 throw std::domain_error(
"cannot use insert() with " + type_name());
5106 return insert(pos, val);
5139 if (pos.m_object !=
this)
5141 throw std::domain_error(
"iterator does not fit current value");
5146 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5151 throw std::domain_error(
"cannot use insert() with " + type_name());
5190 throw std::domain_error(
"cannot use insert() with " + type_name());
5194 if (pos.m_object !=
this)
5196 throw std::domain_error(
"iterator does not fit current value");
5200 if (first.m_object != last.m_object)
5202 throw std::domain_error(
"iterators do not fit");
5205 if (first.m_object ==
this or last.m_object ==
this)
5207 throw std::domain_error(
"passed iterators may not belong to container");
5212 result.m_it.array_iterator = m_value.array->insert(
5213 pos.m_it.array_iterator,
5214 first.m_it.array_iterator,
5215 last.m_it.array_iterator);
5248 throw std::domain_error(
"cannot use insert() with " + type_name());
5252 if (pos.m_object !=
this)
5254 throw std::domain_error(
"iterator does not fit current value");
5259 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5281 std::is_nothrow_move_constructible<value_t>::value and
5282 std::is_nothrow_move_assignable<value_t>::value and
5283 std::is_nothrow_move_constructible<json_value>::value and
5284 std::is_nothrow_move_assignable<json_value>::value
5287 std::swap(m_type, other.m_type);
5288 std::swap(m_value, other.m_value);
5317 std::swap(*(m_value.array), other);
5321 throw std::domain_error(
"cannot use swap() with " + type_name());
5350 std::swap(*(m_value.object), other);
5354 throw std::domain_error(
"cannot use swap() with " + type_name());
5383 std::swap(*(m_value.string), other);
5387 throw std::domain_error(
"cannot use swap() with " + type_name());
5413 static constexpr std::array<uint8_t, 8> order = {{
5426 if (lhs == value_t::discarded or rhs == value_t::discarded)
5431 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
5460 const auto lhs_type = lhs.type();
5461 const auto rhs_type = rhs.type();
5463 if (lhs_type == rhs_type)
5467 case value_t::array:
5469 return *lhs.m_value.array == *rhs.m_value.array;
5471 case value_t::object:
5473 return *lhs.m_value.object == *rhs.m_value.object;
5479 case value_t::string:
5481 return *lhs.m_value.string == *rhs.m_value.string;
5483 case value_t::boolean:
5485 return lhs.m_value.boolean == rhs.m_value.boolean;
5487 case value_t::number_integer:
5489 return lhs.m_value.number_integer == rhs.m_value.number_integer;
5491 case value_t::number_unsigned:
5493 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5495 case value_t::number_float:
5497 return lhs.m_value.number_float == rhs.m_value.number_float;
5505 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5507 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5509 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5511 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_integer);
5513 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5515 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5517 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5519 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5521 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5523 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5525 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5527 return lhs.m_value.number_integer ==
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5583 return not (lhs == rhs);
5615 return not v.is_null();
5644 const auto lhs_type = lhs.type();
5645 const auto rhs_type = rhs.type();
5647 if (lhs_type == rhs_type)
5651 case value_t::array:
5653 return *lhs.m_value.array < *rhs.m_value.array;
5655 case value_t::object:
5657 return *lhs.m_value.object < *rhs.m_value.object;
5663 case value_t::string:
5665 return *lhs.m_value.string < *rhs.m_value.string;
5667 case value_t::boolean:
5669 return lhs.m_value.boolean < rhs.m_value.boolean;
5671 case value_t::number_integer:
5673 return lhs.m_value.number_integer < rhs.m_value.number_integer;
5675 case value_t::number_unsigned:
5677 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5679 case value_t::number_float:
5681 return lhs.m_value.number_float < rhs.m_value.number_float;
5689 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5691 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5693 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5695 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_integer);
5697 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5699 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5701 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5703 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5705 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5707 return lhs.m_value.number_integer <
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5709 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5711 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5717 return operator<(lhs_type, rhs_type);
5739 return not (rhs < lhs);
5761 return not (lhs <= rhs);
5783 return not (lhs < rhs);
5825 const bool pretty_print = (o.width() > 0);
5826 const auto indentation = (pretty_print ? o.width() : 0);
5832 const auto old_locale = o.imbue(std::locale(std::locale(),
new DecimalSeparator));
5839 const auto old_precision = o.precision(std::numeric_limits<double>::digits10);
5842 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
5845 o.imbue(old_locale);
5846 o.precision(old_precision);
5896 template<
class T, std::
size_t N>
5901 return parse(std::begin(array), std::end(array), cb);
5931 template<
typename CharPT,
typename std::enable_if<
5932 std::is_pointer<CharPT>::value and
5933 std::is_integral<typename std::remove_pointer<CharPT>::type>::value and
5934 sizeof(
typename std::remove_pointer<CharPT>::type) == 1,
int>::type = 0>
5938 return parser(reinterpret_cast<const char*>(s), cb).
parse();
5968 return parser(i, cb).
parse();
5977 return parser(i, cb).
parse();
6021 template<
class IteratorType,
typename std::enable_if<
6023 std::random_access_iterator_tag,
6024 typename std::iterator_traits<IteratorType>::iterator_category>::value,
int>::type = 0>
6030 assert(std::accumulate(first, last, std::make_pair<bool, int>(
true, 0),
6031 [&first](std::pair<bool, int> res, decltype(*first) val)
6033 res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
6038 static_assert(
sizeof(
typename std::iterator_traits<IteratorType>::value_type) == 1,
6039 "each element in the iterator range must have the size of 1 byte");
6043 if (std::distance(first, last) <= 0)
6045 return parser(
"").parse();
6048 return parser(first, last, cb).parse();
6091 template<
class ContiguousContainer,
typename std::enable_if<
6092 not std::is_pointer<ContiguousContainer>::value and
6094 std::random_access_iterator_tag,
6095 typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value
6101 return parse(std::begin(c), std::end(c), cb);
6129 j = parser(i).
parse();
6139 j = parser(i).
parse();
6163 std::string type_name()
const 6169 case value_t::object:
6171 case value_t::array:
6173 case value_t::string:
6175 case value_t::boolean:
6177 case value_t::discarded:
6192 static std::size_t extra_space(
const string_t& s) noexcept
6194 return std::accumulate(s.begin(), s.end(),
size_t{},
6195 [](
size_t res,
typename string_t::value_type c)
6213 if (c >= 0x00 and c <= 0x1f)
6242 const auto space = extra_space(s);
6249 string_t result(s.size() + space,
'\\');
6250 std::size_t pos = 0;
6252 for (
const auto& c : s)
6259 result[pos + 1] =
'"';
6275 result[pos + 1] =
'b';
6283 result[pos + 1] =
'f';
6291 result[pos + 1] =
'n';
6299 result[pos + 1] =
'r';
6307 result[pos + 1] =
't';
6314 if (c >= 0x00 and c <= 0x1f)
6318 static const char hexify[16] =
6320 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
6321 '8',
'9',
'a',
'b',
'c',
'd',
'e',
'f' 6326 {
'u',
'0',
'0', hexify[c >> 4], hexify[c & 0x0f]
6364 void dump(std::ostream& o,
6365 const bool pretty_print,
6366 const unsigned int indent_step,
6367 const unsigned int current_indent = 0)
const 6370 unsigned int new_indent = current_indent;
6374 case value_t::object:
6376 if (m_value.object->empty())
6387 new_indent += indent_step;
6391 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
6393 if (i != m_value.object->cbegin())
6395 o << (pretty_print ?
",\n" :
",");
6397 o <<
string_t(new_indent,
' ') <<
"\"" 6398 << escape_string(i->first) <<
"\":" 6399 << (pretty_print ?
" " :
"");
6400 i->second.dump(o, pretty_print, indent_step, new_indent);
6406 new_indent -= indent_step;
6410 o <<
string_t(new_indent,
' ') +
"}";
6414 case value_t::array:
6416 if (m_value.array->empty())
6427 new_indent += indent_step;
6431 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6433 if (i != m_value.array->cbegin())
6435 o << (pretty_print ?
",\n" :
",");
6438 i->dump(o, pretty_print, indent_step, new_indent);
6444 new_indent -= indent_step;
6448 o <<
string_t(new_indent,
' ') <<
"]";
6452 case value_t::string:
6454 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
6458 case value_t::boolean:
6460 o << (m_value.boolean ?
"true" :
"false");
6464 case value_t::number_integer:
6466 o << m_value.number_integer;
6470 case value_t::number_unsigned:
6472 o << m_value.number_unsigned;
6476 case value_t::number_float:
6478 if (m_value.number_float == 0)
6481 o << (std::signbit(m_value.number_float) ?
"-0.0" :
"0.0");
6485 o << m_value.number_float;
6490 case value_t::discarded:
6510 value_t m_type = value_t::null;
6513 json_value m_value = {};
6530 class primitive_iterator_t
6534 void set_begin() noexcept
6540 void set_end() noexcept
6546 constexpr
bool is_begin()
const noexcept
6548 return (m_it == begin_value);
6552 constexpr
bool is_end()
const noexcept
6554 return (m_it == end_value);
6574 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6584 struct internal_iterator
6587 typename object_t::iterator object_iterator;
6589 typename array_t::iterator array_iterator;
6591 primitive_iterator_t primitive_iterator;
6594 internal_iterator() noexcept
6595 : object_iterator(), array_iterator(), primitive_iterator()
6600 template<
typename IteratorType>
6601 class iteration_proxy
6605 class iteration_proxy_internal
6609 IteratorType anchor;
6611 size_t array_index = 0;
6614 explicit iteration_proxy_internal(IteratorType it) noexcept
6619 iteration_proxy_internal& operator*()
6625 iteration_proxy_internal& operator++()
6634 bool operator!= (
const iteration_proxy_internal& o)
const 6636 return anchor != o.anchor;
6642 assert(anchor.m_object !=
nullptr);
6644 switch (anchor.m_object->type())
6647 case value_t::array:
6649 return std::to_string(array_index);
6653 case value_t::object:
6655 return anchor.key();
6667 typename IteratorType::reference value()
const 6669 return anchor.value();
6674 typename IteratorType::reference container;
6678 explicit iteration_proxy(
typename IteratorType::reference cont)
6683 iteration_proxy_internal begin() noexcept
6685 return iteration_proxy_internal(container.begin());
6689 iteration_proxy_internal end() noexcept
6691 return iteration_proxy_internal(container.end());
6715 class const_iterator :
public std::iterator<std::random_access_iterator_tag, const basic_json>
6744 assert(m_object !=
nullptr);
6746 switch (m_object->m_type)
6750 m_it.object_iterator =
typename object_t::iterator();
6756 m_it.array_iterator =
typename array_t::iterator();
6762 m_it.primitive_iterator = primitive_iterator_t();
6774 : m_object(other.m_object)
6776 if (m_object !=
nullptr)
6778 switch (m_object->m_type)
6782 m_it.object_iterator = other.m_it.object_iterator;
6788 m_it.array_iterator = other.m_it.array_iterator;
6794 m_it.primitive_iterator = other.m_it.primitive_iterator;
6807 : m_object(other.m_object), m_it(other.m_it)
6816 std::is_nothrow_move_constructible<pointer>::value and
6817 std::is_nothrow_move_assignable<pointer>::value and
6818 std::is_nothrow_move_constructible<internal_iterator>::value and
6819 std::is_nothrow_move_assignable<internal_iterator>::value
6822 std::swap(m_object, other.m_object);
6823 std::swap(m_it, other.m_it);
6832 void set_begin() noexcept
6834 assert(m_object !=
nullptr);
6836 switch (m_object->m_type)
6840 m_it.object_iterator = m_object->m_value.object->begin();
6846 m_it.array_iterator = m_object->m_value.array->begin();
6853 m_it.primitive_iterator.set_end();
6859 m_it.primitive_iterator.set_begin();
6869 void set_end() noexcept
6871 assert(m_object !=
nullptr);
6873 switch (m_object->m_type)
6877 m_it.object_iterator = m_object->m_value.object->end();
6883 m_it.array_iterator = m_object->m_value.array->end();
6889 m_it.primitive_iterator.set_end();
6902 assert(m_object !=
nullptr);
6904 switch (m_object->m_type)
6908 assert(m_it.object_iterator != m_object->m_value.object->end());
6909 return m_it.object_iterator->second;
6914 assert(m_it.array_iterator != m_object->m_value.array->end());
6915 return *m_it.array_iterator;
6920 throw std::out_of_range(
"cannot get value");
6925 if (m_it.primitive_iterator.is_begin())
6931 throw std::out_of_range(
"cannot get value");
6943 assert(m_object !=
nullptr);
6945 switch (m_object->m_type)
6949 assert(m_it.object_iterator != m_object->m_value.object->end());
6950 return &(m_it.object_iterator->second);
6955 assert(m_it.array_iterator != m_object->m_value.array->end());
6956 return &*m_it.array_iterator;
6961 if (m_it.primitive_iterator.is_begin())
6967 throw std::out_of_range(
"cannot get value");
6979 auto result = *
this;
6990 assert(m_object !=
nullptr);
6992 switch (m_object->m_type)
6996 std::advance(m_it.object_iterator, 1);
7002 std::advance(m_it.array_iterator, 1);
7008 ++m_it.primitive_iterator;
7022 auto result = *
this;
7033 assert(m_object !=
nullptr);
7035 switch (m_object->m_type)
7039 std::advance(m_it.object_iterator, -1);
7045 std::advance(m_it.array_iterator, -1);
7051 --m_it.primitive_iterator;
7066 if (m_object != other.m_object)
7068 throw std::domain_error(
"cannot compare iterators of different containers");
7071 assert(m_object !=
nullptr);
7073 switch (m_object->m_type)
7077 return (m_it.object_iterator == other.m_it.object_iterator);
7082 return (m_it.array_iterator == other.m_it.array_iterator);
7087 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
7098 return not operator==(other);
7108 if (m_object != other.m_object)
7110 throw std::domain_error(
"cannot compare iterators of different containers");
7113 assert(m_object !=
nullptr);
7115 switch (m_object->m_type)
7119 throw std::domain_error(
"cannot compare order of object iterators");
7124 return (m_it.array_iterator < other.m_it.array_iterator);
7129 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
7140 return not other.operator < (*this);
7149 return not operator<=(other);
7158 return not operator<(other);
7167 assert(m_object !=
nullptr);
7169 switch (m_object->m_type)
7173 throw std::domain_error(
"cannot use offsets with object iterators");
7178 std::advance(m_it.array_iterator, i);
7184 m_it.primitive_iterator += i;
7198 return operator+=(-i);
7207 auto result = *
this;
7218 auto result = *
this;
7229 assert(m_object !=
nullptr);
7231 switch (m_object->m_type)
7235 throw std::domain_error(
"cannot use offsets with object iterators");
7240 return m_it.array_iterator - other.m_it.array_iterator;
7245 return m_it.primitive_iterator - other.m_it.primitive_iterator;
7256 assert(m_object !=
nullptr);
7258 switch (m_object->m_type)
7262 throw std::domain_error(
"cannot use operator[] for object iterators");
7267 return *std::next(m_it.array_iterator, n);
7272 throw std::out_of_range(
"cannot get value");
7277 if (m_it.primitive_iterator == -n)
7283 throw std::out_of_range(
"cannot get value");
7293 typename object_t::key_type
key()
const 7295 assert(m_object !=
nullptr);
7297 if (m_object->is_object())
7299 return m_it.object_iterator->first;
7303 throw std::domain_error(
"cannot use key() for non-object iterators");
7320 internal_iterator m_it = internal_iterator();
7357 std::is_nothrow_move_constructible<pointer>::value and
7358 std::is_nothrow_move_assignable<pointer>::value and
7359 std::is_nothrow_move_constructible<internal_iterator>::value and
7360 std::is_nothrow_move_assignable<internal_iterator>::value
7363 base_iterator::operator=(other);
7370 return const_cast<reference>(base_iterator::operator*());
7376 return const_cast<pointer>(base_iterator::operator->());
7383 base_iterator::operator++();
7390 base_iterator::operator++();
7398 base_iterator::operator--();
7405 base_iterator::operator--();
7412 base_iterator::operator+=(i);
7419 base_iterator::operator-=(i);
7426 auto result = *
this;
7434 auto result = *
this;
7442 return base_iterator::operator-(other);
7448 return const_cast<reference>(base_iterator::operator[](n));
7454 return const_cast<reference>(base_iterator::value());
7475 template<
typename Base>
7497 return base_iterator::operator++(1);
7503 base_iterator::operator++();
7510 return base_iterator::operator--(1);
7516 base_iterator::operator--();
7523 base_iterator::operator+=(i);
7530 auto result = *
this;
7538 auto result = *
this;
7546 return this->base() - other.base();
7552 return *(this->operator+(n));
7556 typename object_t::key_type
key()
const 7558 auto it = --this->base();
7565 auto it = --this->base();
7566 return it.operator * ();
7587 enum class token_type
7606 using lexer_char_t =
unsigned char;
7609 lexer(
const lexer_char_t* buff,
const size_t len) noexcept
7612 assert(m_content !=
nullptr);
7613 m_start = m_cursor = m_content;
7614 m_limit = m_content + len;
7618 explicit lexer(std::istream& s)
7619 : m_stream(&s), m_line_buffer()
7625 if (m_line_buffer.size() >= 3 and m_line_buffer.substr(0, 3) ==
"\xEF\xBB\xBF")
7627 m_line_buffer[0] =
' ';
7628 m_line_buffer[1] =
' ';
7629 m_line_buffer[2] =
' ';
7635 lexer(
const lexer&) =
delete;
7636 lexer operator=(
const lexer&) =
delete;
7661 static string_t to_unicode(
const std::size_t codepoint1,
7662 const std::size_t codepoint2 = 0)
7665 std::size_t codepoint = codepoint1;
7668 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7671 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7685 throw std::invalid_argument(
"missing or wrong low surrogate");
7691 if (codepoint < 0x80)
7694 result.append(1, static_cast<typename string_t::value_type>(codepoint));
7696 else if (codepoint <= 0x7ff)
7699 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7700 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7702 else if (codepoint <= 0xffff)
7705 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7706 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7707 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7709 else if (codepoint <= 0x10ffff)
7712 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7713 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7714 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7715 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7719 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
7726 static std::string token_type_name(
const token_type t)
7730 case token_type::uninitialized:
7731 return "<uninitialized>";
7732 case token_type::literal_true:
7733 return "true literal";
7734 case token_type::literal_false:
7735 return "false literal";
7736 case token_type::literal_null:
7737 return "null literal";
7738 case token_type::value_string:
7739 return "string literal";
7740 case token_type::value_number:
7741 return "number literal";
7742 case token_type::begin_array:
7744 case token_type::begin_object:
7746 case token_type::end_array:
7748 case token_type::end_object:
7750 case token_type::name_separator:
7752 case token_type::value_separator:
7754 case token_type::parse_error:
7755 return "<parse error>";
7756 case token_type::end_of_input:
7757 return "end of input";
7761 return "unknown token";
7796 assert(m_start !=
nullptr);
7801 unsigned int yyaccept = 0;
7802 static const unsigned char yybm[] =
7804 0, 0, 0, 0, 0, 0, 0, 0,
7805 0, 32, 32, 0, 0, 32, 0, 0,
7806 0, 0, 0, 0, 0, 0, 0, 0,
7807 0, 0, 0, 0, 0, 0, 0, 0,
7808 160, 128, 0, 128, 128, 128, 128, 128,
7809 128, 128, 128, 128, 128, 128, 128, 128,
7810 192, 192, 192, 192, 192, 192, 192, 192,
7811 192, 192, 128, 128, 128, 128, 128, 128,
7812 128, 128, 128, 128, 128, 128, 128, 128,
7813 128, 128, 128, 128, 128, 128, 128, 128,
7814 128, 128, 128, 128, 128, 128, 128, 128,
7815 128, 128, 128, 128, 0, 128, 128, 128,
7816 128, 128, 128, 128, 128, 128, 128, 128,
7817 128, 128, 128, 128, 128, 128, 128, 128,
7818 128, 128, 128, 128, 128, 128, 128, 128,
7819 128, 128, 128, 128, 128, 128, 128, 128,
7820 0, 0, 0, 0, 0, 0, 0, 0,
7821 0, 0, 0, 0, 0, 0, 0, 0,
7822 0, 0, 0, 0, 0, 0, 0, 0,
7823 0, 0, 0, 0, 0, 0, 0, 0,
7824 0, 0, 0, 0, 0, 0, 0, 0,
7825 0, 0, 0, 0, 0, 0, 0, 0,
7826 0, 0, 0, 0, 0, 0, 0, 0,
7827 0, 0, 0, 0, 0, 0, 0, 0,
7828 0, 0, 0, 0, 0, 0, 0, 0,
7829 0, 0, 0, 0, 0, 0, 0, 0,
7830 0, 0, 0, 0, 0, 0, 0, 0,
7831 0, 0, 0, 0, 0, 0, 0, 0,
7832 0, 0, 0, 0, 0, 0, 0, 0,
7833 0, 0, 0, 0, 0, 0, 0, 0,
7834 0, 0, 0, 0, 0, 0, 0, 0,
7835 0, 0, 0, 0, 0, 0, 0, 0,
7837 if ((m_limit - m_cursor) < 5)
7839 fill_line_buffer(5);
7842 if (yybm[0 + yych] & 32)
7844 goto basic_json_parser_6;
7854 goto basic_json_parser_2;
7858 goto basic_json_parser_4;
7860 goto basic_json_parser_9;
7866 goto basic_json_parser_4;
7870 goto basic_json_parser_10;
7872 goto basic_json_parser_12;
7881 goto basic_json_parser_4;
7885 goto basic_json_parser_13;
7887 goto basic_json_parser_15;
7893 goto basic_json_parser_17;
7897 goto basic_json_parser_4;
7899 goto basic_json_parser_19;
7911 goto basic_json_parser_21;
7913 goto basic_json_parser_4;
7919 goto basic_json_parser_23;
7923 goto basic_json_parser_4;
7925 goto basic_json_parser_24;
7934 goto basic_json_parser_25;
7936 goto basic_json_parser_4;
7942 goto basic_json_parser_26;
7946 goto basic_json_parser_28;
7948 goto basic_json_parser_4;
7952 basic_json_parser_2:
7955 last_token_type = token_type::end_of_input;
7958 basic_json_parser_4:
7960 basic_json_parser_5:
7962 last_token_type = token_type::parse_error;
7965 basic_json_parser_6:
7967 if (m_limit <= m_cursor)
7969 fill_line_buffer(1);
7972 if (yybm[0 + yych] & 32)
7974 goto basic_json_parser_6;
7979 basic_json_parser_9:
7981 yych = *(m_marker = ++m_cursor);
7984 goto basic_json_parser_5;
7988 goto basic_json_parser_31;
7992 goto basic_json_parser_5;
7996 goto basic_json_parser_31;
7998 goto basic_json_parser_5;
7999 basic_json_parser_10:
8002 last_token_type = token_type::value_separator;
8005 basic_json_parser_12:
8009 goto basic_json_parser_5;
8013 goto basic_json_parser_13;
8017 goto basic_json_parser_15;
8019 goto basic_json_parser_5;
8020 basic_json_parser_13:
8022 yych = *(m_marker = ++m_cursor);
8027 goto basic_json_parser_43;
8034 goto basic_json_parser_44;
8038 goto basic_json_parser_44;
8041 basic_json_parser_14:
8043 last_token_type = token_type::value_number;
8046 basic_json_parser_15:
8048 m_marker = ++m_cursor;
8049 if ((m_limit - m_cursor) < 3)
8051 fill_line_buffer(3);
8054 if (yybm[0 + yych] & 64)
8056 goto basic_json_parser_15;
8062 goto basic_json_parser_43;
8064 goto basic_json_parser_14;
8070 goto basic_json_parser_44;
8074 goto basic_json_parser_44;
8076 goto basic_json_parser_14;
8078 basic_json_parser_17:
8081 last_token_type = token_type::name_separator;
8084 basic_json_parser_19:
8087 last_token_type = token_type::begin_array;
8090 basic_json_parser_21:
8093 last_token_type = token_type::end_array;
8096 basic_json_parser_23:
8098 yych = *(m_marker = ++m_cursor);
8101 goto basic_json_parser_45;
8103 goto basic_json_parser_5;
8104 basic_json_parser_24:
8106 yych = *(m_marker = ++m_cursor);
8109 goto basic_json_parser_46;
8111 goto basic_json_parser_5;
8112 basic_json_parser_25:
8114 yych = *(m_marker = ++m_cursor);
8117 goto basic_json_parser_47;
8119 goto basic_json_parser_5;
8120 basic_json_parser_26:
8123 last_token_type = token_type::begin_object;
8126 basic_json_parser_28:
8129 last_token_type = token_type::end_object;
8132 basic_json_parser_30:
8134 if (m_limit <= m_cursor)
8136 fill_line_buffer(1);
8139 basic_json_parser_31:
8140 if (yybm[0 + yych] & 128)
8142 goto basic_json_parser_30;
8150 goto basic_json_parser_32;
8154 goto basic_json_parser_33;
8156 goto basic_json_parser_35;
8162 goto basic_json_parser_32;
8166 goto basic_json_parser_36;
8168 goto basic_json_parser_37;
8177 goto basic_json_parser_39;
8179 goto basic_json_parser_38;
8185 goto basic_json_parser_40;
8189 goto basic_json_parser_41;
8193 goto basic_json_parser_42;
8197 basic_json_parser_32:
8198 m_cursor = m_marker;
8201 goto basic_json_parser_5;
8205 goto basic_json_parser_14;
8207 basic_json_parser_33:
8210 last_token_type = token_type::value_string;
8213 basic_json_parser_35:
8215 if (m_limit <= m_cursor)
8217 fill_line_buffer(1);
8226 goto basic_json_parser_30;
8230 goto basic_json_parser_32;
8232 goto basic_json_parser_30;
8240 goto basic_json_parser_32;
8242 goto basic_json_parser_30;
8248 goto basic_json_parser_30;
8250 goto basic_json_parser_32;
8260 goto basic_json_parser_30;
8264 goto basic_json_parser_30;
8266 goto basic_json_parser_32;
8274 goto basic_json_parser_30;
8276 goto basic_json_parser_32;
8282 goto basic_json_parser_30;
8286 goto basic_json_parser_48;
8288 goto basic_json_parser_32;
8292 basic_json_parser_36:
8294 if (m_limit <= m_cursor)
8296 fill_line_buffer(1);
8301 goto basic_json_parser_32;
8305 goto basic_json_parser_30;
8307 goto basic_json_parser_32;
8308 basic_json_parser_37:
8310 if (m_limit <= m_cursor)
8312 fill_line_buffer(1);
8317 goto basic_json_parser_32;
8321 goto basic_json_parser_36;
8323 goto basic_json_parser_32;
8324 basic_json_parser_38:
8326 if (m_limit <= m_cursor)
8328 fill_line_buffer(1);
8333 goto basic_json_parser_32;
8337 goto basic_json_parser_36;
8339 goto basic_json_parser_32;
8340 basic_json_parser_39:
8342 if (m_limit <= m_cursor)
8344 fill_line_buffer(1);
8349 goto basic_json_parser_32;
8353 goto basic_json_parser_36;
8355 goto basic_json_parser_32;
8356 basic_json_parser_40:
8358 if (m_limit <= m_cursor)
8360 fill_line_buffer(1);
8365 goto basic_json_parser_32;
8369 goto basic_json_parser_38;
8371 goto basic_json_parser_32;
8372 basic_json_parser_41:
8374 if (m_limit <= m_cursor)
8376 fill_line_buffer(1);
8381 goto basic_json_parser_32;
8385 goto basic_json_parser_38;
8387 goto basic_json_parser_32;
8388 basic_json_parser_42:
8390 if (m_limit <= m_cursor)
8392 fill_line_buffer(1);
8397 goto basic_json_parser_32;
8401 goto basic_json_parser_38;
8403 goto basic_json_parser_32;
8404 basic_json_parser_43:
8408 goto basic_json_parser_32;
8412 goto basic_json_parser_49;
8414 goto basic_json_parser_32;
8415 basic_json_parser_44:
8421 goto basic_json_parser_51;
8423 goto basic_json_parser_32;
8429 goto basic_json_parser_51;
8433 goto basic_json_parser_32;
8437 goto basic_json_parser_52;
8439 goto basic_json_parser_32;
8441 basic_json_parser_45:
8445 goto basic_json_parser_54;
8447 goto basic_json_parser_32;
8448 basic_json_parser_46:
8452 goto basic_json_parser_55;
8454 goto basic_json_parser_32;
8455 basic_json_parser_47:
8459 goto basic_json_parser_56;
8461 goto basic_json_parser_32;
8462 basic_json_parser_48:
8464 if (m_limit <= m_cursor)
8466 fill_line_buffer(1);
8473 goto basic_json_parser_32;
8477 goto basic_json_parser_57;
8479 goto basic_json_parser_32;
8485 goto basic_json_parser_57;
8489 goto basic_json_parser_32;
8493 goto basic_json_parser_57;
8495 goto basic_json_parser_32;
8497 basic_json_parser_49:
8499 m_marker = ++m_cursor;
8500 if ((m_limit - m_cursor) < 3)
8502 fill_line_buffer(3);
8509 goto basic_json_parser_14;
8513 goto basic_json_parser_49;
8515 goto basic_json_parser_14;
8521 goto basic_json_parser_44;
8525 goto basic_json_parser_44;
8527 goto basic_json_parser_14;
8529 basic_json_parser_51:
8533 goto basic_json_parser_32;
8537 goto basic_json_parser_32;
8539 basic_json_parser_52:
8541 if (m_limit <= m_cursor)
8543 fill_line_buffer(1);
8548 goto basic_json_parser_14;
8552 goto basic_json_parser_52;
8554 goto basic_json_parser_14;
8555 basic_json_parser_54:
8559 goto basic_json_parser_58;
8561 goto basic_json_parser_32;
8562 basic_json_parser_55:
8566 goto basic_json_parser_59;
8568 goto basic_json_parser_32;
8569 basic_json_parser_56:
8573 goto basic_json_parser_61;
8575 goto basic_json_parser_32;
8576 basic_json_parser_57:
8578 if (m_limit <= m_cursor)
8580 fill_line_buffer(1);
8587 goto basic_json_parser_32;
8591 goto basic_json_parser_63;
8593 goto basic_json_parser_32;
8599 goto basic_json_parser_63;
8603 goto basic_json_parser_32;
8607 goto basic_json_parser_63;
8609 goto basic_json_parser_32;
8611 basic_json_parser_58:
8615 goto basic_json_parser_64;
8617 goto basic_json_parser_32;
8618 basic_json_parser_59:
8621 last_token_type = token_type::literal_null;
8624 basic_json_parser_61:
8627 last_token_type = token_type::literal_true;
8630 basic_json_parser_63:
8632 if (m_limit <= m_cursor)
8634 fill_line_buffer(1);
8641 goto basic_json_parser_32;
8645 goto basic_json_parser_66;
8647 goto basic_json_parser_32;
8653 goto basic_json_parser_66;
8657 goto basic_json_parser_32;
8661 goto basic_json_parser_66;
8663 goto basic_json_parser_32;
8665 basic_json_parser_64:
8668 last_token_type = token_type::literal_false;
8671 basic_json_parser_66:
8673 if (m_limit <= m_cursor)
8675 fill_line_buffer(1);
8682 goto basic_json_parser_32;
8686 goto basic_json_parser_30;
8688 goto basic_json_parser_32;
8694 goto basic_json_parser_30;
8698 goto basic_json_parser_32;
8702 goto basic_json_parser_30;
8704 goto basic_json_parser_32;
8710 return last_token_type;
8741 void fill_line_buffer(
size_t n = 0)
8744 const auto offset_start = m_start - m_content;
8746 const auto offset_marker = (m_marker ==
nullptr) ? 0 : m_marker - m_start;
8748 const auto offset_cursor = m_cursor - m_start;
8751 if (m_stream ==
nullptr or m_stream->eof())
8754 if (m_start != reinterpret_cast<const lexer_char_t*>(m_line_buffer.data()))
8757 m_line_buffer.clear();
8758 for (m_cursor = m_start; m_cursor != m_limit; ++m_cursor)
8760 m_line_buffer.append(1, static_cast<const char>(*m_cursor));
8766 m_line_buffer.append(1,
'\x00');
8767 m_line_buffer.append(n - 1,
'\x01');
8772 m_line_buffer.erase(0, static_cast<size_t>(offset_start));
8775 std::getline(*m_stream, line,
'\n');
8777 m_line_buffer += line +
"\n";
8781 m_content =
reinterpret_cast<const lexer_char_t*
>(m_line_buffer.c_str());
8782 assert(m_content !=
nullptr);
8783 m_start = m_content;
8784 m_marker = m_start + offset_marker;
8785 m_cursor = m_start + offset_cursor;
8786 m_limit = m_start + m_line_buffer.size();
8792 assert(m_start !=
nullptr);
8793 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8794 static_cast<size_t>(m_cursor - m_start));
8856 assert(m_cursor - m_start >= 2);
8859 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8862 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8918 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8919 4).c_str(),
nullptr, 16);
8922 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8925 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
8927 throw std::invalid_argument(
"missing low surrogate");
8931 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8932 (i + 7), 4).c_str(),
nullptr, 16);
8933 result += to_unicode(codepoint, codepoint2);
8937 else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF)
8940 throw std::invalid_argument(
"missing high surrogate");
8945 result += to_unicode(codepoint);
8957 result.append(1, static_cast<typename string_t::value_type>(*i));
8979 long double str_to_float_t(
long double* ,
char** endptr)
const 8981 return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8999 double str_to_float_t(
double* ,
char** endptr)
const 9001 return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
9019 float str_to_float_t(
float* ,
char** endptr)
const 9021 return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
9047 assert(m_start !=
nullptr);
9049 const lexer::lexer_char_t* curptr = m_start;
9063 type = value_t::number_integer;
9064 max =
static_cast<uint64_t
>((std::numeric_limits<number_integer_t>::max)()) + 1;
9069 type = value_t::number_unsigned;
9070 max =
static_cast<uint64_t
>((std::numeric_limits<number_unsigned_t>::max)());
9074 for (; curptr < m_cursor; curptr++)
9077 if (*curptr < '0' || *curptr >
'9')
9082 type = value_t::number_float;
9087 type = value_t::number_float;
9092 if (type != value_t::number_float)
9095 auto temp = value * 10 + *curptr -
'0';
9098 if (temp < value || temp > max)
9101 type = value_t::number_float;
9112 if (type == value_t::number_unsigned)
9114 result.m_value.number_unsigned = value;
9116 else if (type == value_t::number_integer)
9123 result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(
nullptr), NULL);
9126 if (not std::isfinite(result.m_value.number_float))
9128 type = value_t::null;
9129 result.m_value = basic_json::json_value();
9134 result.m_type = type;
9139 std::istream* m_stream =
nullptr;
9143 const lexer_char_t* m_content =
nullptr;
9145 const lexer_char_t* m_start =
nullptr;
9147 const lexer_char_t* m_marker =
nullptr;
9149 const lexer_char_t* m_cursor =
nullptr;
9151 const lexer_char_t* m_limit =
nullptr;
9153 token_type last_token_type = token_type::end_of_input;
9167 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), strlen(buff))
9172 : callback(cb), m_lexer(is)
9176 template<
class IteratorType,
typename std::enable_if<
9177 std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
9180 parser(IteratorType first, IteratorType last,
const parser_callback_t cb =
nullptr)
9182 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
9183 static_cast<size_t>(std::distance(first, last)))
9193 result.assert_invariant();
9195 expect(lexer::token_type::end_of_input);
9206 auto result =
basic_json(value_t::discarded);
9210 case lexer::token_type::begin_object:
9212 if (keep and (not callback
9213 or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
9216 result.m_type = value_t::object;
9217 result.m_value = value_t::object;
9224 if (last_token == lexer::token_type::end_object)
9227 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
9235 unexpect(lexer::token_type::value_separator);
9241 if (last_token == lexer::token_type::value_separator)
9247 expect(lexer::token_type::value_string);
9248 const auto key = m_lexer.get_string();
9250 bool keep_tag =
false;
9256 keep_tag = callback(depth, parse_event_t::key, k);
9266 expect(lexer::token_type::name_separator);
9270 auto value = parse_internal(keep);
9271 if (keep and keep_tag and not value.is_discarded())
9273 result[key] = std::move(value);
9276 while (last_token == lexer::token_type::value_separator);
9279 expect(lexer::token_type::end_object);
9281 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
9289 case lexer::token_type::begin_array:
9291 if (keep and (not callback
9292 or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
9295 result.m_type = value_t::array;
9296 result.m_value = value_t::array;
9303 if (last_token == lexer::token_type::end_array)
9306 if (callback and not callback(--depth, parse_event_t::array_end, result))
9314 unexpect(lexer::token_type::value_separator);
9320 if (last_token == lexer::token_type::value_separator)
9326 auto value = parse_internal(keep);
9327 if (keep and not value.is_discarded())
9329 result.push_back(std::move(value));
9332 while (last_token == lexer::token_type::value_separator);
9335 expect(lexer::token_type::end_array);
9337 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
9345 case lexer::token_type::literal_null:
9348 result.m_type = value_t::null;
9352 case lexer::token_type::value_string:
9354 const auto s = m_lexer.get_string();
9360 case lexer::token_type::literal_true:
9363 result.m_type = value_t::boolean;
9364 result.m_value =
true;
9368 case lexer::token_type::literal_false:
9371 result.m_type = value_t::boolean;
9372 result.m_value =
false;
9376 case lexer::token_type::value_number:
9378 m_lexer.get_number(result);
9386 unexpect(last_token);
9390 if (keep and callback and not callback(depth, parse_event_t::value, result))
9398 typename lexer::token_type get_token()
9400 last_token = m_lexer.scan();
9404 void expect(
typename lexer::token_type t)
const 9406 if (t != last_token)
9408 std::string error_msg =
"parse error - unexpected ";
9409 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
9411 lexer::token_type_name(last_token));
9412 error_msg +=
"; expected " + lexer::token_type_name(t);
9413 throw std::invalid_argument(error_msg);
9417 void unexpect(
typename lexer::token_type t)
const 9419 if (t == last_token)
9421 std::string error_msg =
"parse error - unexpected ";
9422 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
9424 lexer::token_type_name(last_token));
9425 throw std::invalid_argument(error_msg);
9435 typename lexer::token_type last_token = lexer::token_type::uninitialized;
9481 : reference_tokens(split(s))
9499 std::string to_string()
const noexcept
9501 return std::accumulate(reference_tokens.begin(),
9502 reference_tokens.end(), std::string{},
9503 [](
const std::string & a,
const std::string & b)
9505 return a +
"/" + escape(b);
9510 operator std::string()
const 9517 std::string pop_back()
9521 throw std::domain_error(
"JSON pointer has no parent");
9524 auto last = reference_tokens.back();
9525 reference_tokens.pop_back();
9530 bool is_root()
const 9532 return reference_tokens.empty();
9539 throw std::domain_error(
"JSON pointer has no parent");
9543 result.reference_tokens = {reference_tokens[0]};
9558 for (
const auto& reference_token : reference_tokens)
9560 switch (result->m_type)
9564 if (reference_token ==
"0")
9567 result = &result->operator[](0);
9572 result = &result->operator[](reference_token);
9577 case value_t::object:
9580 result = &result->operator[](reference_token);
9584 case value_t::array:
9587 result = &result->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9600 throw std::domain_error(
"invalid value to unflatten");
9629 for (
const auto& reference_token : reference_tokens)
9632 if (ptr->m_type == value_t::null)
9635 const bool nums = std::all_of(reference_token.begin(),
9636 reference_token.end(),
9639 return std::isdigit(x);
9644 if (nums or reference_token ==
"-")
9646 *ptr = value_t::array;
9650 *ptr = value_t::object;
9654 switch (ptr->m_type)
9656 case value_t::object:
9659 ptr = &ptr->operator[](reference_token);
9663 case value_t::array:
9666 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9668 throw std::domain_error(
"array index must not begin with '0'");
9671 if (reference_token ==
"-")
9674 ptr = &ptr->operator[](ptr->m_value.array->size());
9679 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9686 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9696 for (
const auto& reference_token : reference_tokens)
9698 switch (ptr->m_type)
9700 case value_t::object:
9703 ptr = &ptr->
at(reference_token);
9707 case value_t::array:
9709 if (reference_token ==
"-")
9712 throw std::out_of_range(
"array index '-' (" +
9713 std::to_string(ptr->m_value.array->size()) +
9714 ") is out of range");
9718 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9720 throw std::domain_error(
"array index must not begin with '0'");
9724 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9730 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9748 for (
const auto& reference_token : reference_tokens)
9750 switch (ptr->m_type)
9752 case value_t::object:
9755 ptr = &ptr->operator[](reference_token);
9759 case value_t::array:
9761 if (reference_token ==
"-")
9764 throw std::out_of_range(
"array index '-' (" +
9765 std::to_string(ptr->m_value.array->size()) +
9766 ") is out of range");
9770 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9772 throw std::domain_error(
"array index must not begin with '0'");
9776 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9782 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9792 for (
const auto& reference_token : reference_tokens)
9794 switch (ptr->m_type)
9796 case value_t::object:
9799 ptr = &ptr->
at(reference_token);
9803 case value_t::array:
9805 if (reference_token ==
"-")
9808 throw std::out_of_range(
"array index '-' (" +
9809 std::to_string(ptr->m_value.array->size()) +
9810 ") is out of range");
9814 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9816 throw std::domain_error(
"array index must not begin with '0'");
9820 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9826 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9835 static std::vector<std::string> split(
const std::string& reference_string)
9837 std::vector<std::string> result;
9840 if (reference_string.empty())
9846 if (reference_string[0] !=
'/')
9848 throw std::domain_error(
"JSON pointer must be empty or begin with '/'");
9856 size_t slash = reference_string.find_first_of(
"/", 1),
9865 slash = reference_string.find_first_of(
"/", start))
9869 auto reference_token = reference_string.substr(start, slash - start);
9872 for (
size_t pos = reference_token.find_first_of(
"~");
9873 pos != std::string::npos;
9874 pos = reference_token.find_first_of(
"~", pos + 1))
9876 assert(reference_token[pos] ==
'~');
9879 if (pos == reference_token.size() - 1 or
9880 (reference_token[pos + 1] !=
'0' and
9881 reference_token[pos + 1] !=
'1'))
9883 throw std::domain_error(
"escape error: '~' must be followed with '0' or '1'");
9888 unescape(reference_token);
9889 result.push_back(reference_token);
9910 static void replace_substring(std::string& s,
9911 const std::string& f,
9912 const std::string& t)
9914 assert(not f.empty());
9917 size_t pos = s.find(f);
9918 pos != std::string::npos;
9919 s.replace(pos, f.size(), t),
9920 pos = s.find(f, pos + t.size())
9925 static std::string escape(std::string s)
9928 replace_substring(s,
"~",
"~0");
9929 replace_substring(s,
"/",
"~1");
9934 static void unescape(std::string& s)
9937 replace_substring(s,
"~1",
"/");
9939 replace_substring(s,
"~0",
"~");
9949 static void flatten(
const std::string& reference_string,
9953 switch (value.m_type)
9955 case value_t::array:
9957 if (value.m_value.array->empty())
9960 result[reference_string] =
nullptr;
9965 for (
size_t i = 0; i < value.m_value.array->size(); ++i)
9967 flatten(reference_string +
"/" + std::to_string(i),
9968 value.m_value.array->operator[](i), result);
9974 case value_t::object:
9976 if (value.m_value.object->empty())
9979 result[reference_string] =
nullptr;
9984 for (
const auto& element : *value.m_value.object)
9986 flatten(reference_string +
"/" + escape(element.first),
9987 element.second, result);
9996 result[reference_string] = value;
10011 throw std::domain_error(
"only objects can be unflattened");
10017 for (
const auto& element : *value.m_value.object)
10019 if (not element.second.is_primitive())
10021 throw std::domain_error(
"values in object must be primitive");
10029 json_pointer(element.first).get_and_create(result) = element.second;
10037 std::vector<std::string> reference_tokens {};
10082 return ptr.get_unchecked(
this);
10109 return ptr.get_unchecked(
this);
10134 return ptr.get_checked(
this);
10159 return ptr.get_checked(
this);
10187 json_pointer::flatten(
"", *
this, result);
10220 return json_pointer::unflatten(*
this);
10274 enum class patch_operations {add,
remove, replace, move, copy, test, invalid};
10276 const auto get_op = [](
const std::string op)
10280 return patch_operations::add;
10282 if (op ==
"remove")
10284 return patch_operations::remove;
10286 if (op ==
"replace")
10288 return patch_operations::replace;
10292 return patch_operations::move;
10296 return patch_operations::copy;
10300 return patch_operations::test;
10303 return patch_operations::invalid;
10318 if (top_pointer != ptr)
10320 result.
at(top_pointer);
10324 const auto last_path = ptr.pop_back();
10327 switch (parent.m_type)
10329 case value_t::null:
10330 case value_t::object:
10333 parent[last_path] = val;
10337 case value_t::array:
10339 if (last_path ==
"-")
10346 const auto idx = std::stoi(last_path);
10347 if (static_cast<size_type>(idx) > parent.
size())
10350 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
10371 const auto operation_remove = [&result](
json_pointer & ptr)
10374 const auto last_path = ptr.pop_back();
10381 auto it = parent.
find(last_path);
10382 if (it != parent.
end())
10388 throw std::out_of_range(
"key '" + last_path +
"' not found");
10394 parent.
erase(static_cast<size_type>(std::stoi(last_path)));
10402 throw std::invalid_argument(
"JSON patch must be an array of objects");
10406 for (
const auto& val : json_patch)
10409 const auto get_value = [&val](
const std::string & op,
10410 const std::string & member,
10414 auto it = val.m_value.object->find(member);
10417 const auto error_msg = (op ==
"op") ?
"operation" :
"operation '" + op +
"'";
10420 if (it == val.m_value.object->end())
10422 throw std::invalid_argument(error_msg +
" must have member '" + member +
"'");
10426 if (string_type and not it->second.is_string())
10428 throw std::invalid_argument(error_msg +
" must have string member '" + member +
"'");
10436 if (not val.is_object())
10438 throw std::invalid_argument(
"JSON patch must be an array of objects");
10442 const std::string op = get_value(
"op",
"op",
true);
10443 const std::string path = get_value(op,
"path",
true);
10446 switch (get_op(op))
10448 case patch_operations::add:
10450 operation_add(ptr, get_value(
"add",
"value",
false));
10454 case patch_operations::remove:
10456 operation_remove(ptr);
10460 case patch_operations::replace:
10463 result.
at(ptr) = get_value(
"replace",
"value",
false);
10467 case patch_operations::move:
10469 const std::string from_path = get_value(
"move",
"from",
true);
10479 operation_remove(from_ptr);
10480 operation_add(ptr, v);
10484 case patch_operations::copy:
10486 const std::string from_path = get_value(
"copy",
"from",
true);;
10490 result[ptr] = result.
at(from_ptr);
10494 case patch_operations::test:
10496 bool success =
false;
10501 success = (result.
at(ptr) == get_value(
"test",
"value",
false));
10503 catch (std::out_of_range&)
10511 throw std::domain_error(
"unsuccessful: " + val.dump());
10517 case patch_operations::invalid:
10521 throw std::invalid_argument(
"operation value '" + op +
"' is invalid");
10563 const std::string& path =
"")
10569 if (source == target)
10574 if (source.
type() != target.
type())
10586 switch (source.
type())
10588 case value_t::array:
10592 while (i < source.
size() and i < target.
size())
10595 auto temp_diff = diff(source[i], target[i], path +
"/" + std::to_string(i));
10596 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10605 while (i < source.
size())
10609 result.insert(result.begin() + end_index, object(
10612 {
"path", path +
"/" + std::to_string(i)}
10618 while (i < target.
size())
10623 {
"path", path +
"/" + std::to_string(i)},
10624 {
"value", target[i]}
10632 case value_t::object:
10635 for (
auto it = source.
begin(); it != source.
end(); ++it)
10638 const auto key = json_pointer::escape(it.key());
10640 if (target.
find(it.key()) != target.
end())
10643 auto temp_diff = diff(it.value(), target[it.key()], path +
"/" + key);
10644 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10649 result.push_back(
object(
10652 {
"path", path +
"/" + key}
10658 for (
auto it = target.
begin(); it != target.
end(); ++it)
10660 if (source.
find(it.key()) == source.
end())
10663 const auto key = json_pointer::escape(it.key());
10667 {
"path", path +
"/" + key},
10668 {
"value", it.value()}
10728 is_nothrow_move_constructible<nlohmann::json>::value and
10729 is_nothrow_move_assignable<nlohmann::json>::value
10747 const auto& h = hash<nlohmann::json::string_t>();
10766 inline nlohmann::json operator "" _json(
const char* s, std::size_t n)
10790 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 10791 #pragma GCC diagnostic pop const_iterator(pointer object) noexcept
constructor for a given JSON instance
size_type max_size() const noexcept
returns the maximum possible number of elements
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
constexpr bool is_array() const noexcept
return whether value is an array
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
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)
reference value() const
return the value of an iterator
const_iterator end() const noexcept
returns a const iterator to one past the last element
constexpr bool is_primitive() const noexcept
return whether type is primitive
constexpr bool is_null() const noexcept
return whether value is null
ValueType get() const
get a value (explicit)
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
constexpr bool is_structured() const noexcept
return whether type is structured
json_reverse_iterator & operator--()
pre-decrement (–it)
void clear() noexcept
clears the contents
const_reference operator[](size_type idx) const
access specified array element
static basic_json parse(const CharPT s, const parser_callback_t cb=nullptr)
deserialize from string literal
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
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
size_type count(typename object_t::key_type key) const
returns the number of occurrences of a key in a JSON object
static basic_json parse(IteratorType first, IteratorType last, const parser_callback_t cb=nullptr)
deserialize from an iterator range with contiguous storage
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
const_iterator operator-(difference_type i)
subtract from iterator
BooleanType boolean_t
a type for a boolean
reference operator+=(const typename object_t::value_type &val)
add an object to an object
basic_json(const typename string_t::value_type *val)
create a string (explicit)
object_t::key_type key() const
return the key of an object iterator
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)
reference operator*() const
return a reference to the value pointed to by the iterator
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
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)
static basic_json parse(T(&array)[N], const parser_callback_t cb=nullptr)
deserialize from an array
constexpr bool is_object() const noexcept
return whether value is an object
friend bool operator==(std::nullptr_t, const_reference v) 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*
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_iterator operator+(difference_type i)
add to iterator
a mutable random access iterator for the basic_json class
const_iterator operator++(int)
post-increment (it++)
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
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)
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
static basic_json parse(std::istream &&i, const parser_callback_t cb=nullptr)
deserialize from stream
pointer operator->() const
dereference the iterator
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
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
const_reference front() const
access the first element
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)
const_iterator cbegin() const noexcept
returns a const iterator to the first element
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)
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
void push_back(const typename object_t::value_type &val)
add an object to an object
bool empty() const noexcept
checks whether the container is empty
void push_back(std::initializer_list< basic_json > init)
add an object to an object
json_pointer(const std::string &s="")
create JSON pointer
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
IteratorType erase(IteratorType pos)
remove element given an iterator
static allocator_type get_allocator()
returns the allocator associated with the container
json_reverse_iterator operator+(difference_type i) const
add to iterator
string_t dump(const int indent=-1) const
serialization
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
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
std::size_t size_type
a type to represent container sizes
JSON_DEPRECATED basic_json(std::istream &i, const parser_callback_t cb=nullptr)
construct a JSON value given an input stream
const_iterator(const iterator &other) noexcept
copy constructor given a non-const iterator
basic_json(const CompatibleArrayType &val)
create an array (implicit)
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
object_t::key_type key() const
return the key of an object iterator
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)
iterator operator++(int)
post-increment (it++)
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
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
object (unordered set of name/value pairs)
iterator operator--(int)
post-decrement (it–)
iterator operator-(difference_type i)
subtract from iterator
const_iterator & operator--()
pre-decrement (–it)
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
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
static basic_json parse(const ContiguousContainer &c, const parser_callback_t cb=nullptr)
deserialize from a container with contiguous storage
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
value_type & reference
the type of an element reference
pointer operator->() const
dereference the iterator
ReferenceType get_ref() const
get a reference value (implicit)
reference value() const
return the value of an iterator
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
size_type size() const noexcept
returns the number of elements
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
constexpr bool is_string() const noexcept
return whether value is a string
void swap(string_t &other)
exchanges the values
reference operator[](difference_type n) const
access to successor
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
const_reference at(size_type idx) const
access specified array element with bounds checking
reference value() const
return the value of an iterator
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
const_reference operator[](T *key) const
read-only access specified object element
NumberFloatType number_float_t
a type for a number (floating-point)
value_t
the JSON type enumeration
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
std::ptrdiff_t difference_type
a type to represent differences between iterators
difference_type operator-(const const_iterator &other) const
return difference
void swap(array_t &other)
exchanges the values
reference operator[](difference_type n) const
access to successor
typename Base::reference reference
the reference type for the pointed-to element
void push_back(basic_json &&val)
add an object to an array
array (ordered collection of values)
json_reverse_iterator & operator++()
pre-increment (++it)
difference_type operator-(const iterator &other) const
return difference
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
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
static basic_json parse(std::istream &i, const parser_callback_t cb=nullptr)
deserialize from stream
ValueType value(const json_pointer &ptr, ValueType default_value) const
access specified object element via JSON Pointer with default value
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
bool operator!=(const const_iterator &other) const
comparison: not equal
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
constexpr bool is_boolean() const noexcept
return whether value is a boolean
bool operator==(const const_iterator &other) const
comparison: equal
bool operator<=(const const_iterator &other) const
comparison: less than or equal
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
string_t value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
friend class basic_json
allow basic_json to access private members
reference operator[](difference_type n) const
access to successor
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)
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
difference_type operator-(const json_reverse_iterator &other) const
return difference
const_reference back() const
access the last element
const_iterator & operator++()
pre-increment (++it)
constexpr bool is_number() const noexcept
return whether value is a number
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
const_iterator begin() const noexcept
returns a const iterator to the first element
bool operator>(const const_iterator &other) const
comparison: greater than
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
iterator begin() noexcept
returns an iterator to the first element
const_iterator cend() const noexcept
returns a const iterator to one past the last element
basic_json(const CompatibleObjectType &val)
create an object (implicit)
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
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
reference operator+=(basic_json &&val)
add an object to an array
a const random access iterator for the basic_json class
a template for a reverse iterator class
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
json_reverse_iterator & operator+=(difference_type i)
add to iterator
reference at(size_type idx)
access specified array element with bounds checking
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
constexpr bool is_discarded() const noexcept
return whether value is discarded
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
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
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
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)
reference operator*() const
return a reference to the value pointed to by the iterator
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
bool operator<(const const_iterator &other) const
comparison: smaller
reference operator[](T *key)
access specified object element
parse_event_t
JSON callback events.