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()
7627 lexer(
const lexer&) =
delete;
7628 lexer operator=(
const lexer&) =
delete;
7653 static string_t to_unicode(
const std::size_t codepoint1,
7654 const std::size_t codepoint2 = 0)
7657 std::size_t codepoint = codepoint1;
7660 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7663 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7677 throw std::invalid_argument(
"missing or wrong low surrogate");
7683 if (codepoint < 0x80)
7686 result.append(1, static_cast<typename string_t::value_type>(codepoint));
7688 else if (codepoint <= 0x7ff)
7691 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7692 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7694 else if (codepoint <= 0xffff)
7697 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7698 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7699 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7701 else if (codepoint <= 0x10ffff)
7704 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7705 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
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)));
7711 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
7718 static std::string token_type_name(
const token_type t)
7722 case token_type::uninitialized:
7723 return "<uninitialized>";
7724 case token_type::literal_true:
7725 return "true literal";
7726 case token_type::literal_false:
7727 return "false literal";
7728 case token_type::literal_null:
7729 return "null literal";
7730 case token_type::value_string:
7731 return "string literal";
7732 case token_type::value_number:
7733 return "number literal";
7734 case token_type::begin_array:
7736 case token_type::begin_object:
7738 case token_type::end_array:
7740 case token_type::end_object:
7742 case token_type::name_separator:
7744 case token_type::value_separator:
7746 case token_type::parse_error:
7747 return "<parse error>";
7748 case token_type::end_of_input:
7749 return "end of input";
7753 return "unknown token";
7788 assert(m_start !=
nullptr);
7793 unsigned int yyaccept = 0;
7794 static const unsigned char yybm[] = {
7795 0, 0, 0, 0, 0, 0, 0, 0,
7796 0, 32, 32, 0, 0, 32, 0, 0,
7797 0, 0, 0, 0, 0, 0, 0, 0,
7798 0, 0, 0, 0, 0, 0, 0, 0,
7799 160, 128, 0, 128, 128, 128, 128, 128,
7800 128, 128, 128, 128, 128, 128, 128, 128,
7801 192, 192, 192, 192, 192, 192, 192, 192,
7802 192, 192, 128, 128, 128, 128, 128, 128,
7803 128, 128, 128, 128, 128, 128, 128, 128,
7804 128, 128, 128, 128, 128, 128, 128, 128,
7805 128, 128, 128, 128, 128, 128, 128, 128,
7806 128, 128, 128, 128, 0, 128, 128, 128,
7807 128, 128, 128, 128, 128, 128, 128, 128,
7808 128, 128, 128, 128, 128, 128, 128, 128,
7809 128, 128, 128, 128, 128, 128, 128, 128,
7810 128, 128, 128, 128, 128, 128, 128, 128,
7811 128, 128, 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, 128, 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 128, 128, 128, 128, 128, 128, 128, 128,
7821 128, 128, 128, 128, 128, 128, 128, 128,
7822 128, 128, 128, 128, 128, 128, 128, 128,
7823 128, 128, 128, 128, 128, 128, 128, 128,
7824 128, 128, 128, 128, 128, 128, 128, 128,
7825 128, 128, 128, 128, 128, 128, 128, 128,
7826 128, 128, 128, 128, 128, 128, 128, 128,
7828 if ((m_limit - m_cursor) < 5) fill_line_buffer();
7830 if (yybm[0+yych] & 32) {
7831 goto basic_json_parser_6;
7836 if (yych <= 0x00)
goto basic_json_parser_2;
7837 if (yych <=
'!')
goto basic_json_parser_4;
7838 goto basic_json_parser_9;
7840 if (yych <=
'+')
goto basic_json_parser_4;
7841 if (yych <=
',')
goto basic_json_parser_10;
7842 goto basic_json_parser_12;
7846 if (yych <=
'/')
goto basic_json_parser_4;
7847 if (yych <=
'0')
goto basic_json_parser_13;
7848 goto basic_json_parser_15;
7850 if (yych <=
':')
goto basic_json_parser_17;
7851 if (yych ==
'[')
goto basic_json_parser_19;
7852 goto basic_json_parser_4;
7858 if (yych <=
']')
goto basic_json_parser_21;
7859 if (yych <=
'e')
goto basic_json_parser_4;
7860 goto basic_json_parser_23;
7862 if (yych ==
'n')
goto basic_json_parser_24;
7863 if (yych <=
's')
goto basic_json_parser_4;
7864 goto basic_json_parser_25;
7868 if (yych ==
'{')
goto basic_json_parser_26;
7869 goto basic_json_parser_4;
7871 if (yych <=
'}')
goto basic_json_parser_28;
7872 if (yych == 0xEF)
goto basic_json_parser_30;
7873 goto basic_json_parser_4;
7877 basic_json_parser_2:
7879 { last_token_type = token_type::end_of_input;
break; }
7880 basic_json_parser_4:
7882 basic_json_parser_5:
7883 { last_token_type = token_type::parse_error;
break; }
7884 basic_json_parser_6:
7886 if (m_limit <= m_cursor) fill_line_buffer();
7888 if (yybm[0+yych] & 32) {
7889 goto basic_json_parser_6;
7892 basic_json_parser_9:
7894 yych = *(m_marker = ++m_cursor);
7895 if (yych <= 0x1F)
goto basic_json_parser_5;
7896 goto basic_json_parser_32;
7897 basic_json_parser_10:
7899 { last_token_type = token_type::value_separator;
break; }
7900 basic_json_parser_12:
7902 if (yych <=
'/')
goto basic_json_parser_5;
7903 if (yych <=
'0')
goto basic_json_parser_13;
7904 if (yych <=
'9')
goto basic_json_parser_15;
7905 goto basic_json_parser_5;
7906 basic_json_parser_13:
7908 yych = *(m_marker = ++m_cursor);
7910 if (yych ==
'.')
goto basic_json_parser_37;
7912 if (yych <=
'E')
goto basic_json_parser_38;
7913 if (yych ==
'e')
goto basic_json_parser_38;
7915 basic_json_parser_14:
7916 { last_token_type = token_type::value_number;
break; }
7917 basic_json_parser_15:
7919 m_marker = ++m_cursor;
7920 if ((m_limit - m_cursor) < 3) fill_line_buffer();
7922 if (yybm[0+yych] & 64) {
7923 goto basic_json_parser_15;
7926 if (yych ==
'.')
goto basic_json_parser_37;
7927 goto basic_json_parser_14;
7929 if (yych <=
'E')
goto basic_json_parser_38;
7930 if (yych ==
'e')
goto basic_json_parser_38;
7931 goto basic_json_parser_14;
7933 basic_json_parser_17:
7935 { last_token_type = token_type::name_separator;
break; }
7936 basic_json_parser_19:
7938 { last_token_type = token_type::begin_array;
break; }
7939 basic_json_parser_21:
7941 { last_token_type = token_type::end_array;
break; }
7942 basic_json_parser_23:
7944 yych = *(m_marker = ++m_cursor);
7945 if (yych ==
'a')
goto basic_json_parser_39;
7946 goto basic_json_parser_5;
7947 basic_json_parser_24:
7949 yych = *(m_marker = ++m_cursor);
7950 if (yych ==
'u')
goto basic_json_parser_40;
7951 goto basic_json_parser_5;
7952 basic_json_parser_25:
7954 yych = *(m_marker = ++m_cursor);
7955 if (yych ==
'r')
goto basic_json_parser_41;
7956 goto basic_json_parser_5;
7957 basic_json_parser_26:
7959 { last_token_type = token_type::begin_object;
break; }
7960 basic_json_parser_28:
7962 { last_token_type = token_type::end_object;
break; }
7963 basic_json_parser_30:
7965 yych = *(m_marker = ++m_cursor);
7966 if (yych == 0xBB)
goto basic_json_parser_42;
7967 goto basic_json_parser_5;
7968 basic_json_parser_31:
7970 if (m_limit <= m_cursor) fill_line_buffer();
7972 basic_json_parser_32:
7973 if (yybm[0+yych] & 128) {
7974 goto basic_json_parser_31;
7976 if (yych <= 0x1F)
goto basic_json_parser_33;
7977 if (yych <=
'"')
goto basic_json_parser_34;
7978 goto basic_json_parser_36;
7979 basic_json_parser_33:
7980 m_cursor = m_marker;
7981 if (yyaccept == 0) {
7982 goto basic_json_parser_5;
7984 goto basic_json_parser_14;
7986 basic_json_parser_34:
7988 { last_token_type = token_type::value_string;
break; }
7989 basic_json_parser_36:
7991 if (m_limit <= m_cursor) fill_line_buffer();
7995 if (yych ==
'"')
goto basic_json_parser_31;
7996 if (yych <=
'.')
goto basic_json_parser_33;
7997 goto basic_json_parser_31;
8000 if (yych <=
'[')
goto basic_json_parser_33;
8001 goto basic_json_parser_31;
8003 if (yych ==
'b')
goto basic_json_parser_31;
8004 goto basic_json_parser_33;
8009 if (yych <=
'f')
goto basic_json_parser_31;
8010 if (yych ==
'n')
goto basic_json_parser_31;
8011 goto basic_json_parser_33;
8014 if (yych <=
'r')
goto basic_json_parser_31;
8015 goto basic_json_parser_33;
8017 if (yych <=
't')
goto basic_json_parser_31;
8018 if (yych <=
'u')
goto basic_json_parser_43;
8019 goto basic_json_parser_33;
8023 basic_json_parser_37:
8025 if (yych <=
'/')
goto basic_json_parser_33;
8026 if (yych <=
'9')
goto basic_json_parser_44;
8027 goto basic_json_parser_33;
8028 basic_json_parser_38:
8031 if (yych ==
'+')
goto basic_json_parser_46;
8032 goto basic_json_parser_33;
8034 if (yych <=
'-')
goto basic_json_parser_46;
8035 if (yych <=
'/')
goto basic_json_parser_33;
8036 if (yych <=
'9')
goto basic_json_parser_47;
8037 goto basic_json_parser_33;
8039 basic_json_parser_39:
8041 if (yych ==
'l')
goto basic_json_parser_49;
8042 goto basic_json_parser_33;
8043 basic_json_parser_40:
8045 if (yych ==
'l')
goto basic_json_parser_50;
8046 goto basic_json_parser_33;
8047 basic_json_parser_41:
8049 if (yych ==
'u')
goto basic_json_parser_51;
8050 goto basic_json_parser_33;
8051 basic_json_parser_42:
8053 if (yych == 0xBF)
goto basic_json_parser_52;
8054 goto basic_json_parser_33;
8055 basic_json_parser_43:
8057 if (m_limit <= m_cursor) fill_line_buffer();
8060 if (yych <=
'/')
goto basic_json_parser_33;
8061 if (yych <=
'9')
goto basic_json_parser_54;
8062 goto basic_json_parser_33;
8064 if (yych <=
'F')
goto basic_json_parser_54;
8065 if (yych <=
'`')
goto basic_json_parser_33;
8066 if (yych <=
'f')
goto basic_json_parser_54;
8067 goto basic_json_parser_33;
8069 basic_json_parser_44:
8071 m_marker = ++m_cursor;
8072 if ((m_limit - m_cursor) < 3) fill_line_buffer();
8075 if (yych <=
'/')
goto basic_json_parser_14;
8076 if (yych <=
'9')
goto basic_json_parser_44;
8077 goto basic_json_parser_14;
8079 if (yych <=
'E')
goto basic_json_parser_38;
8080 if (yych ==
'e')
goto basic_json_parser_38;
8081 goto basic_json_parser_14;
8083 basic_json_parser_46:
8085 if (yych <=
'/')
goto basic_json_parser_33;
8086 if (yych >=
':')
goto basic_json_parser_33;
8087 basic_json_parser_47:
8089 if (m_limit <= m_cursor) fill_line_buffer();
8091 if (yych <=
'/')
goto basic_json_parser_14;
8092 if (yych <=
'9')
goto basic_json_parser_47;
8093 goto basic_json_parser_14;
8094 basic_json_parser_49:
8096 if (yych ==
's')
goto basic_json_parser_55;
8097 goto basic_json_parser_33;
8098 basic_json_parser_50:
8100 if (yych ==
'l')
goto basic_json_parser_56;
8101 goto basic_json_parser_33;
8102 basic_json_parser_51:
8104 if (yych ==
'e')
goto basic_json_parser_58;
8105 goto basic_json_parser_33;
8106 basic_json_parser_52:
8109 basic_json_parser_54:
8111 if (m_limit <= m_cursor) fill_line_buffer();
8114 if (yych <=
'/')
goto basic_json_parser_33;
8115 if (yych <=
'9')
goto basic_json_parser_60;
8116 goto basic_json_parser_33;
8118 if (yych <=
'F')
goto basic_json_parser_60;
8119 if (yych <=
'`')
goto basic_json_parser_33;
8120 if (yych <=
'f')
goto basic_json_parser_60;
8121 goto basic_json_parser_33;
8123 basic_json_parser_55:
8125 if (yych ==
'e')
goto basic_json_parser_61;
8126 goto basic_json_parser_33;
8127 basic_json_parser_56:
8129 { last_token_type = token_type::literal_null;
break; }
8130 basic_json_parser_58:
8132 { last_token_type = token_type::literal_true;
break; }
8133 basic_json_parser_60:
8135 if (m_limit <= m_cursor) fill_line_buffer();
8138 if (yych <=
'/')
goto basic_json_parser_33;
8139 if (yych <=
'9')
goto basic_json_parser_63;
8140 goto basic_json_parser_33;
8142 if (yych <=
'F')
goto basic_json_parser_63;
8143 if (yych <=
'`')
goto basic_json_parser_33;
8144 if (yych <=
'f')
goto basic_json_parser_63;
8145 goto basic_json_parser_33;
8147 basic_json_parser_61:
8149 { last_token_type = token_type::literal_false;
break; }
8150 basic_json_parser_63:
8152 if (m_limit <= m_cursor) fill_line_buffer();
8155 if (yych <=
'/')
goto basic_json_parser_33;
8156 if (yych <=
'9')
goto basic_json_parser_31;
8157 goto basic_json_parser_33;
8159 if (yych <=
'F')
goto basic_json_parser_31;
8160 if (yych <=
'`')
goto basic_json_parser_33;
8161 if (yych <=
'f')
goto basic_json_parser_31;
8162 goto basic_json_parser_33;
8168 return last_token_type;
8199 void fill_line_buffer()
8202 const auto offset_start = m_start - m_content;
8204 const auto offset_marker = (m_marker ==
nullptr) ? 0 : m_marker - m_start;
8206 const auto offset_cursor = m_cursor - m_start;
8209 if (m_stream ==
nullptr or m_stream->eof())
8212 m_line_buffer.clear();
8213 for (m_cursor = m_start; m_cursor != m_limit; ++m_cursor)
8215 m_line_buffer.append(1, static_cast<const char>(*m_cursor));
8221 m_line_buffer.append(5,
'\0');
8226 m_line_buffer.erase(0, static_cast<size_t>(offset_start));
8229 std::getline(*m_stream, line);
8231 m_line_buffer += line +
"\n";
8235 m_content =
reinterpret_cast<const lexer_char_t*
>(m_line_buffer.c_str());
8236 assert(m_content !=
nullptr);
8237 m_start = m_content;
8238 m_marker = m_start + offset_marker;
8239 m_cursor = m_start + offset_cursor;
8240 m_limit = m_start + m_line_buffer.size();
8246 assert(m_start !=
nullptr);
8247 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8248 static_cast<size_t>(m_cursor - m_start));
8310 assert(m_cursor - m_start >= 2);
8313 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8316 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8372 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8373 4).c_str(),
nullptr, 16);
8376 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8379 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
8381 throw std::invalid_argument(
"missing low surrogate");
8385 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8386 (i + 7), 4).c_str(),
nullptr, 16);
8387 result += to_unicode(codepoint, codepoint2);
8394 result += to_unicode(codepoint);
8406 result.append(1, static_cast<typename string_t::value_type>(*i));
8428 long double str_to_float_t(
long double* ,
char** endptr)
const 8430 return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8448 double str_to_float_t(
double* ,
char** endptr)
const 8450 return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8468 float str_to_float_t(
float* ,
char** endptr)
const 8470 return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8496 assert(m_start !=
nullptr);
8498 const lexer::lexer_char_t* curptr = m_start;
8512 type = value_t::number_integer;
8513 max =
static_cast<uint64_t
>((std::numeric_limits<number_integer_t>::max)()) + 1;
8518 type = value_t::number_unsigned;
8519 max =
static_cast<uint64_t
>((std::numeric_limits<number_unsigned_t>::max)());
8523 for (; curptr < m_cursor; curptr++)
8526 if (*curptr < '0' || *curptr >
'9')
8531 type = value_t::number_float;
8536 type = value_t::number_float;
8541 if (type != value_t::number_float)
8544 auto temp = value * 10 + *curptr -
'0';
8547 if (temp < value || temp > max)
8550 type = value_t::number_float;
8561 if (type == value_t::number_unsigned)
8563 result.m_value.number_unsigned = value;
8565 else if (type == value_t::number_integer)
8572 result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(
nullptr), NULL);
8576 result.m_type = type;
8581 std::istream* m_stream =
nullptr;
8585 const lexer_char_t* m_content =
nullptr;
8587 const lexer_char_t* m_start =
nullptr;
8589 const lexer_char_t* m_marker =
nullptr;
8591 const lexer_char_t* m_cursor =
nullptr;
8593 const lexer_char_t* m_limit =
nullptr;
8595 token_type last_token_type = token_type::end_of_input;
8609 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), strlen(buff))
8614 : callback(cb), m_lexer(is)
8618 template<
class IteratorType,
typename std::enable_if<
8619 std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
8622 parser(IteratorType first, IteratorType last,
const parser_callback_t cb =
nullptr)
8624 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
8625 static_cast<size_t>(std::distance(first, last)))
8635 result.assert_invariant();
8637 expect(lexer::token_type::end_of_input);
8648 auto result =
basic_json(value_t::discarded);
8652 case lexer::token_type::begin_object:
8654 if (keep and (not callback
8655 or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
8658 result.m_type = value_t::object;
8659 result.m_value = value_t::object;
8666 if (last_token == lexer::token_type::end_object)
8669 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8677 unexpect(lexer::token_type::value_separator);
8683 if (last_token == lexer::token_type::value_separator)
8689 expect(lexer::token_type::value_string);
8690 const auto key = m_lexer.get_string();
8692 bool keep_tag =
false;
8698 keep_tag = callback(depth, parse_event_t::key, k);
8708 expect(lexer::token_type::name_separator);
8712 auto value = parse_internal(keep);
8713 if (keep and keep_tag and not value.is_discarded())
8715 result[key] = std::move(value);
8718 while (last_token == lexer::token_type::value_separator);
8721 expect(lexer::token_type::end_object);
8723 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8731 case lexer::token_type::begin_array:
8733 if (keep and (not callback
8734 or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
8737 result.m_type = value_t::array;
8738 result.m_value = value_t::array;
8745 if (last_token == lexer::token_type::end_array)
8748 if (callback and not callback(--depth, parse_event_t::array_end, result))
8756 unexpect(lexer::token_type::value_separator);
8762 if (last_token == lexer::token_type::value_separator)
8768 auto value = parse_internal(keep);
8769 if (keep and not value.is_discarded())
8771 result.push_back(std::move(value));
8774 while (last_token == lexer::token_type::value_separator);
8777 expect(lexer::token_type::end_array);
8779 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8787 case lexer::token_type::literal_null:
8790 result.m_type = value_t::null;
8794 case lexer::token_type::value_string:
8796 const auto s = m_lexer.get_string();
8802 case lexer::token_type::literal_true:
8805 result.m_type = value_t::boolean;
8806 result.m_value =
true;
8810 case lexer::token_type::literal_false:
8813 result.m_type = value_t::boolean;
8814 result.m_value =
false;
8818 case lexer::token_type::value_number:
8820 m_lexer.get_number(result);
8828 unexpect(last_token);
8832 if (keep and callback and not callback(depth, parse_event_t::value, result))
8840 typename lexer::token_type get_token()
8842 last_token = m_lexer.scan();
8846 void expect(
typename lexer::token_type t)
const 8848 if (t != last_token)
8850 std::string error_msg =
"parse error - unexpected ";
8851 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
8853 lexer::token_type_name(last_token));
8854 error_msg +=
"; expected " + lexer::token_type_name(t);
8855 throw std::invalid_argument(error_msg);
8859 void unexpect(
typename lexer::token_type t)
const 8861 if (t == last_token)
8863 std::string error_msg =
"parse error - unexpected ";
8864 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
8866 lexer::token_type_name(last_token));
8867 throw std::invalid_argument(error_msg);
8877 typename lexer::token_type last_token = lexer::token_type::uninitialized;
8923 : reference_tokens(split(s))
8941 std::string to_string()
const noexcept
8943 return std::accumulate(reference_tokens.begin(),
8944 reference_tokens.end(), std::string{},
8945 [](
const std::string & a,
const std::string & b)
8947 return a +
"/" + escape(b);
8952 operator std::string()
const 8959 std::string pop_back()
8963 throw std::domain_error(
"JSON pointer has no parent");
8966 auto last = reference_tokens.back();
8967 reference_tokens.pop_back();
8972 bool is_root()
const 8974 return reference_tokens.empty();
8981 throw std::domain_error(
"JSON pointer has no parent");
8985 result.reference_tokens = {reference_tokens[0]};
9000 for (
const auto& reference_token : reference_tokens)
9002 switch (result->m_type)
9006 if (reference_token ==
"0")
9009 result = &result->operator[](0);
9014 result = &result->operator[](reference_token);
9019 case value_t::object:
9022 result = &result->operator[](reference_token);
9026 case value_t::array:
9029 result = &result->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9042 throw std::domain_error(
"invalid value to unflatten");
9071 for (
const auto& reference_token : reference_tokens)
9074 if (ptr->m_type == value_t::null)
9077 const bool nums = std::all_of(reference_token.begin(),
9078 reference_token.end(),
9081 return std::isdigit(x);
9086 if (nums or reference_token ==
"-")
9088 *ptr = value_t::array;
9092 *ptr = value_t::object;
9096 switch (ptr->m_type)
9098 case value_t::object:
9101 ptr = &ptr->operator[](reference_token);
9105 case value_t::array:
9108 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9110 throw std::domain_error(
"array index must not begin with '0'");
9113 if (reference_token ==
"-")
9116 ptr = &ptr->operator[](ptr->m_value.array->size());
9121 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9128 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9138 for (
const auto& reference_token : reference_tokens)
9140 switch (ptr->m_type)
9142 case value_t::object:
9145 ptr = &ptr->
at(reference_token);
9149 case value_t::array:
9151 if (reference_token ==
"-")
9154 throw std::out_of_range(
"array index '-' (" +
9155 std::to_string(ptr->m_value.array->size()) +
9156 ") is out of range");
9160 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9162 throw std::domain_error(
"array index must not begin with '0'");
9166 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9172 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9190 for (
const auto& reference_token : reference_tokens)
9192 switch (ptr->m_type)
9194 case value_t::object:
9197 ptr = &ptr->operator[](reference_token);
9201 case value_t::array:
9203 if (reference_token ==
"-")
9206 throw std::out_of_range(
"array index '-' (" +
9207 std::to_string(ptr->m_value.array->size()) +
9208 ") is out of range");
9212 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9214 throw std::domain_error(
"array index must not begin with '0'");
9218 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9224 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9234 for (
const auto& reference_token : reference_tokens)
9236 switch (ptr->m_type)
9238 case value_t::object:
9241 ptr = &ptr->
at(reference_token);
9245 case value_t::array:
9247 if (reference_token ==
"-")
9250 throw std::out_of_range(
"array index '-' (" +
9251 std::to_string(ptr->m_value.array->size()) +
9252 ") is out of range");
9256 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9258 throw std::domain_error(
"array index must not begin with '0'");
9262 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9268 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9277 static std::vector<std::string> split(
const std::string& reference_string)
9279 std::vector<std::string> result;
9282 if (reference_string.empty())
9288 if (reference_string[0] !=
'/')
9290 throw std::domain_error(
"JSON pointer must be empty or begin with '/'");
9298 size_t slash = reference_string.find_first_of(
"/", 1),
9307 slash = reference_string.find_first_of(
"/", start))
9311 auto reference_token = reference_string.substr(start, slash - start);
9314 for (
size_t pos = reference_token.find_first_of(
"~");
9315 pos != std::string::npos;
9316 pos = reference_token.find_first_of(
"~", pos + 1))
9318 assert(reference_token[pos] ==
'~');
9321 if (pos == reference_token.size() - 1 or
9322 (reference_token[pos + 1] !=
'0' and
9323 reference_token[pos + 1] !=
'1'))
9325 throw std::domain_error(
"escape error: '~' must be followed with '0' or '1'");
9330 unescape(reference_token);
9331 result.push_back(reference_token);
9352 static void replace_substring(std::string& s,
9353 const std::string& f,
9354 const std::string& t)
9356 assert(not f.empty());
9359 size_t pos = s.find(f);
9360 pos != std::string::npos;
9361 s.replace(pos, f.size(), t),
9362 pos = s.find(f, pos + t.size())
9367 static std::string escape(std::string s)
9370 replace_substring(s,
"~",
"~0");
9371 replace_substring(s,
"/",
"~1");
9376 static void unescape(std::string& s)
9379 replace_substring(s,
"~1",
"/");
9381 replace_substring(s,
"~0",
"~");
9391 static void flatten(
const std::string& reference_string,
9395 switch (value.m_type)
9397 case value_t::array:
9399 if (value.m_value.array->empty())
9402 result[reference_string] =
nullptr;
9407 for (
size_t i = 0; i < value.m_value.array->size(); ++i)
9409 flatten(reference_string +
"/" + std::to_string(i),
9410 value.m_value.array->operator[](i), result);
9416 case value_t::object:
9418 if (value.m_value.object->empty())
9421 result[reference_string] =
nullptr;
9426 for (
const auto& element : *value.m_value.object)
9428 flatten(reference_string +
"/" + escape(element.first),
9429 element.second, result);
9438 result[reference_string] = value;
9453 throw std::domain_error(
"only objects can be unflattened");
9459 for (
const auto& element : *value.m_value.object)
9461 if (not element.second.is_primitive())
9463 throw std::domain_error(
"values in object must be primitive");
9471 json_pointer(element.first).get_and_create(result) = element.second;
9479 std::vector<std::string> reference_tokens {};
9524 return ptr.get_unchecked(
this);
9551 return ptr.get_unchecked(
this);
9576 return ptr.get_checked(
this);
9601 return ptr.get_checked(
this);
9629 json_pointer::flatten(
"", *
this, result);
9662 return json_pointer::unflatten(*
this);
9716 enum class patch_operations {add,
remove, replace, move, copy, test, invalid};
9718 const auto get_op = [](
const std::string op)
9722 return patch_operations::add;
9726 return patch_operations::remove;
9728 if (op ==
"replace")
9730 return patch_operations::replace;
9734 return patch_operations::move;
9738 return patch_operations::copy;
9742 return patch_operations::test;
9745 return patch_operations::invalid;
9760 if (top_pointer != ptr)
9762 result.
at(top_pointer);
9766 const auto last_path = ptr.pop_back();
9769 switch (parent.m_type)
9772 case value_t::object:
9775 parent[last_path] = val;
9779 case value_t::array:
9781 if (last_path ==
"-")
9788 const auto idx = std::stoi(last_path);
9789 if (static_cast<size_type>(idx) > parent.
size())
9792 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
9813 const auto operation_remove = [&result](
json_pointer & ptr)
9816 const auto last_path = ptr.pop_back();
9823 auto it = parent.
find(last_path);
9824 if (it != parent.
end())
9830 throw std::out_of_range(
"key '" + last_path +
"' not found");
9836 parent.
erase(static_cast<size_type>(std::stoi(last_path)));
9844 throw std::invalid_argument(
"JSON patch must be an array of objects");
9848 for (
const auto& val : json_patch)
9851 const auto get_value = [&val](
const std::string & op,
9852 const std::string & member,
9856 auto it = val.m_value.object->find(member);
9859 const auto error_msg = (op ==
"op") ?
"operation" :
"operation '" + op +
"'";
9862 if (it == val.m_value.object->end())
9864 throw std::invalid_argument(error_msg +
" must have member '" + member +
"'");
9868 if (string_type and not it->second.is_string())
9870 throw std::invalid_argument(error_msg +
" must have string member '" + member +
"'");
9878 if (not val.is_object())
9880 throw std::invalid_argument(
"JSON patch must be an array of objects");
9884 const std::string op = get_value(
"op",
"op",
true);
9885 const std::string path = get_value(op,
"path",
true);
9890 case patch_operations::add:
9892 operation_add(ptr, get_value(
"add",
"value",
false));
9896 case patch_operations::remove:
9898 operation_remove(ptr);
9902 case patch_operations::replace:
9905 result.
at(ptr) = get_value(
"replace",
"value",
false);
9909 case patch_operations::move:
9911 const std::string from_path = get_value(
"move",
"from",
true);
9921 operation_remove(from_ptr);
9922 operation_add(ptr, v);
9926 case patch_operations::copy:
9928 const std::string from_path = get_value(
"copy",
"from",
true);;
9932 result[ptr] = result.
at(from_ptr);
9936 case patch_operations::test:
9938 bool success =
false;
9943 success = (result.
at(ptr) == get_value(
"test",
"value",
false));
9945 catch (std::out_of_range&)
9953 throw std::domain_error(
"unsuccessful: " + val.dump());
9959 case patch_operations::invalid:
9963 throw std::invalid_argument(
"operation value '" + op +
"' is invalid");
10005 const std::string& path =
"")
10011 if (source == target)
10016 if (source.
type() != target.
type())
10028 switch (source.
type())
10030 case value_t::array:
10034 while (i < source.
size() and i < target.
size())
10037 auto temp_diff = diff(source[i], target[i], path +
"/" + std::to_string(i));
10038 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10047 while (i < source.
size())
10051 result.insert(result.begin() + end_index, object(
10054 {
"path", path +
"/" + std::to_string(i)}
10060 while (i < target.
size())
10065 {
"path", path +
"/" + std::to_string(i)},
10066 {
"value", target[i]}
10074 case value_t::object:
10077 for (
auto it = source.
begin(); it != source.
end(); ++it)
10080 const auto key = json_pointer::escape(it.key());
10082 if (target.
find(it.key()) != target.
end())
10085 auto temp_diff = diff(it.value(), target[it.key()], path +
"/" + key);
10086 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10091 result.push_back(
object(
10094 {
"path", path +
"/" + key}
10100 for (
auto it = target.
begin(); it != target.
end(); ++it)
10102 if (source.
find(it.key()) == source.
end())
10105 const auto key = json_pointer::escape(it.key());
10109 {
"path", path +
"/" + key},
10110 {
"value", it.value()}
10170 is_nothrow_move_constructible<nlohmann::json>::value and
10171 is_nothrow_move_assignable<nlohmann::json>::value
10189 const auto& h = hash<nlohmann::json::string_t>();
10207 inline nlohmann::json operator "" _json(
const char* s, std::size_t)
10230 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 10231 #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.