29 #ifndef NLOHMANN_JSON_HPP 30 #define NLOHMANN_JSON_HPP 42 #include <initializer_list> 52 #include <type_traits> 57 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 58 #pragma GCC diagnostic push 59 #pragma GCC diagnostic ignored "-Wfloat-equal" 82 struct has_mapped_type
85 template<
typename C>
static char test(
typename C::mapped_type*);
86 template<
typename C>
static char (&test(...))[2];
88 static constexpr
bool value =
sizeof(test<T>(0)) == 1;
95 class DecimalSeparator :
public std::numpunct<char>
98 char do_decimal_point()
const 178 template<
typename U,
typename V,
typename... Args>
class ObjectType = std::map,
179 template<
typename U,
typename... Args>
class ArrayType = std::vector,
180 class StringType = std::string,
181 class BooleanType = bool,
182 class NumberIntegerType = std::int64_t,
183 class NumberUnsignedType = std::uint64_t,
184 class NumberFloatType = double,
185 template<
typename U>
class AllocatorType = std::allocator
229 using pointer =
typename std::allocator_traits<allocator_type>::pointer;
231 using const_pointer =
typename std::allocator_traits<allocator_type>::const_pointer;
344 using object_t = ObjectType<StringType,
346 std::less<StringType>,
347 AllocatorType<std::pair<
const StringType,
394 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
715 template<
typename T,
typename... Args>
716 static T* create(Args&& ... args)
718 AllocatorType<T> alloc;
719 auto deleter = [&](T * object)
721 alloc.deallocate(
object, 1);
723 std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
724 alloc.construct(
object.
get(), std::forward<Args>(args)...);
725 return object.release();
757 json_value() =
default;
759 json_value(
boolean_t v) noexcept : boolean(v) {}
771 case value_t::object:
773 object = create<object_t>();
779 array = create<array_t>();
783 case value_t::string:
785 string = create<string_t>(
"");
789 case value_t::boolean:
795 case value_t::number_integer:
801 case value_t::number_unsigned:
807 case value_t::number_float:
823 string = create<string_t>(value);
829 object = create<object_t>(value);
833 json_value(
const array_t& value)
835 array = create<array_t>(value);
918 using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
968 : m_type(value_type), m_value(value_type)
995 basic_json() =
default;
1043 : m_type(
value_t::object), m_value(val)
1072 template <
class CompatibleObjectType,
typename 1074 std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1075 std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value,
int>::type
1082 m_value.object = create<object_t>(begin(val), end(val));
1105 : m_type(
value_t::array), m_value(val)
1134 template <
class CompatibleArrayType,
typename 1136 not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1137 not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1138 not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1139 not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1140 not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1141 not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1142 std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value,
int>::type
1149 m_value.array = create<array_t>(begin(val), end(val));
1174 : m_type(
value_t::string), m_value(val)
1224 template <
class CompatibleStringType,
typename 1226 std::is_constructible<string_t, CompatibleStringType>::value,
int>::type
1247 : m_type(value_t::boolean), m_value(val)
1273 template<
typename T,
1274 typename std::enable_if<
1275 not (std::is_same<T, int>::value)
1276 and std::is_same<T, number_integer_t>::value
1280 : m_type(value_t::number_integer), m_value(val)
1309 : m_type(value_t::number_integer),
1310 m_value(static_cast<number_integer_t>(val))
1338 template<
typename CompatibleNumberIntegerType,
typename 1340 std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1341 std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1342 std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1343 CompatibleNumberIntegerType>::type
1346 : m_type(value_t::number_integer),
1347 m_value(static_cast<number_integer_t>(val))
1367 template<
typename T,
1368 typename std::enable_if<
1369 not (std::is_same<T, int>::value)
1370 and std::is_same<T, number_unsigned_t>::value
1374 : m_type(value_t::number_unsigned), m_value(val)
1397 template <
typename CompatibleNumberUnsignedType,
typename 1399 std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1400 std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1401 not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1402 CompatibleNumberUnsignedType>::type
1405 : m_type(value_t::number_unsigned),
1406 m_value(static_cast<number_unsigned_t>(val))
1434 : m_type(value_t::number_float), m_value(val)
1437 if (not std::isfinite(val))
1439 m_type = value_t::null;
1440 m_value = json_value();
1475 template<
typename CompatibleNumberFloatType,
typename =
typename 1477 std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1478 std::is_floating_point<CompatibleNumberFloatType>::value>::type
1554 bool type_deduction =
true,
1555 value_t manual_type = value_t::array)
1558 bool is_an_object =
true;
1562 for (
const auto& element : init)
1564 if (not element.is_array() or element.size() != 2
1565 or not element[0].is_string())
1569 is_an_object =
false;
1575 if (not type_deduction)
1578 if (manual_type == value_t::array)
1580 is_an_object =
false;
1584 if (manual_type == value_t::object and not is_an_object)
1586 throw std::domain_error(
"cannot create object from initializer list");
1593 m_type = value_t::object;
1594 m_value = value_t::object;
1596 assert(m_value.object !=
nullptr);
1598 for (
auto& element : init)
1600 m_value.object->emplace(*(element[0].m_value.string), element[1]);
1606 m_type = value_t::array;
1607 m_value.array = create<array_t>(init);
1645 static basic_json
array(std::initializer_list<basic_json> init =
1646 std::initializer_list<basic_json>())
1648 return basic_json(init,
false, value_t::array);
1685 static basic_json
object(std::initializer_list<basic_json> init =
1686 std::initializer_list<basic_json>())
1688 return basic_json(init,
false, value_t::object);
1712 m_value.array = create<array_t>(cnt, val);
1749 template <
class InputIT,
typename 1751 std::is_same<InputIT, typename basic_json_t::iterator>::value or
1752 std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1755 basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1758 if (first.m_object != last.m_object)
1760 throw std::domain_error(
"iterators are not compatible");
1766 case value_t::boolean:
1767 case value_t::number_float:
1768 case value_t::number_integer:
1769 case value_t::number_unsigned:
1770 case value_t::string:
1772 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1774 throw std::out_of_range(
"iterators out of range");
1787 case value_t::number_integer:
1789 assert(first.m_object !=
nullptr);
1790 m_value.number_integer = first.m_object->m_value.number_integer;
1794 case value_t::number_unsigned:
1796 assert(first.m_object !=
nullptr);
1797 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1801 case value_t::number_float:
1803 assert(first.m_object !=
nullptr);
1804 m_value.number_float = first.m_object->m_value.number_float;
1808 case value_t::boolean:
1810 assert(first.m_object !=
nullptr);
1811 m_value.boolean = first.m_object->m_value.boolean;
1815 case value_t::string:
1817 assert(first.m_object !=
nullptr);
1818 m_value = *first.m_object->m_value.string;
1822 case value_t::object:
1824 m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1828 case value_t::array:
1830 m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1836 assert(first.m_object !=
nullptr);
1837 throw std::domain_error(
"cannot use construct with iterators from " + first.m_object->type_name());
1864 *
this = parser(i, cb).parse();
1894 : m_type(other.m_type)
1898 case value_t::object:
1900 assert(other.m_value.object !=
nullptr);
1901 m_value = *other.m_value.object;
1905 case value_t::array:
1907 assert(other.m_value.array !=
nullptr);
1908 m_value = *other.m_value.array;
1912 case value_t::string:
1914 assert(other.m_value.string !=
nullptr);
1915 m_value = *other.m_value.string;
1919 case value_t::boolean:
1921 m_value = other.m_value.boolean;
1925 case value_t::number_integer:
1927 m_value = other.m_value.number_integer;
1931 case value_t::number_unsigned:
1933 m_value = other.m_value.number_unsigned;
1937 case value_t::number_float:
1939 m_value = other.m_value.number_float;
1969 : m_type(
std::move(other.m_type)),
1970 m_value(
std::move(other.m_value))
1973 other.m_type = value_t::null;
2001 std::is_nothrow_move_constructible<value_t>::value and
2002 std::is_nothrow_move_assignable<value_t>::value and
2003 std::is_nothrow_move_constructible<json_value>::value and
2004 std::is_nothrow_move_assignable<json_value>::value
2008 swap(m_type, other.m_type);
2009 swap(m_value, other.m_value);
2032 case value_t::object:
2034 AllocatorType<object_t> alloc;
2035 alloc.destroy(m_value.object);
2036 alloc.deallocate(m_value.object, 1);
2040 case value_t::array:
2042 AllocatorType<array_t> alloc;
2043 alloc.destroy(m_value.array);
2044 alloc.deallocate(m_value.array, 1);
2048 case value_t::string:
2050 AllocatorType<string_t> alloc;
2051 alloc.destroy(m_value.string);
2052 alloc.deallocate(m_value.string, 1);
2099 std::stringstream ss;
2101 ss.imbue(std::locale(std::locale(),
new DecimalSeparator));
2105 dump(ss,
true, static_cast<unsigned int>(indent));
2165 return is_null() or is_string() or is_boolean() or is_number();
2192 return is_array() or is_object();
2214 return m_type == value_t::null;
2236 return m_type == value_t::boolean;
2266 return is_number_integer() or is_number_float();
2295 return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2323 return m_type == value_t::number_unsigned;
2351 return m_type == value_t::number_float;
2373 return m_type == value_t::object;
2395 return m_type == value_t::array;
2417 return m_type == value_t::string;
2444 return m_type == value_t::discarded;
2478 template <
class T,
typename 2480 std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2481 std::is_convertible<basic_json_t, typename T::mapped_type>::value
2483 T get_impl(T*)
const 2487 assert(m_value.object !=
nullptr);
2488 return T(m_value.object->begin(), m_value.object->end());
2492 throw std::domain_error(
"type must be object, but is " + type_name());
2501 assert(m_value.object !=
nullptr);
2502 return *(m_value.object);
2506 throw std::domain_error(
"type must be object, but is " + type_name());
2511 template <
class T,
typename 2513 std::is_convertible<basic_json_t, typename T::value_type>::value and
2514 not std::is_same<basic_json_t, typename T::value_type>::value and
2515 not std::is_arithmetic<T>::value and
2516 not std::is_convertible<std::string, T>::value and
2517 not has_mapped_type<T>::value
2519 T get_impl(T*)
const 2524 assert(m_value.array !=
nullptr);
2525 std::transform(m_value.array->begin(), m_value.array->end(),
2526 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2528 return i.
get<
typename T::value_type>();
2534 throw std::domain_error(
"type must be array, but is " + type_name());
2539 template <
class T,
typename 2541 std::is_convertible<basic_json_t, T>::value and
2542 not std::is_same<basic_json_t, T>::value
2544 std::vector<T> get_impl(std::vector<T>*)
const 2548 std::vector<T> to_vector;
2549 assert(m_value.array !=
nullptr);
2550 to_vector.reserve(m_value.array->size());
2551 std::transform(m_value.array->begin(), m_value.array->end(),
2552 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2560 throw std::domain_error(
"type must be array, but is " + type_name());
2565 template <
class T,
typename 2567 std::is_same<basic_json, typename T::value_type>::value and
2568 not has_mapped_type<T>::value
2570 T get_impl(T*)
const 2574 assert(m_value.array !=
nullptr);
2575 return T(m_value.array->begin(), m_value.array->end());
2579 throw std::domain_error(
"type must be array, but is " + type_name());
2588 assert(m_value.array !=
nullptr);
2589 return *(m_value.array);
2593 throw std::domain_error(
"type must be array, but is " + type_name());
2598 template <
typename T,
typename 2600 std::is_convertible<string_t, T>::value
2602 T get_impl(T*)
const 2606 assert(m_value.string !=
nullptr);
2607 return *m_value.string;
2611 throw std::domain_error(
"type must be string, but is " + type_name());
2616 template<
typename T,
typename 2618 std::is_arithmetic<T>::value
2620 T get_impl(T*)
const 2624 case value_t::number_integer:
2626 return static_cast<T
>(m_value.number_integer);
2629 case value_t::number_unsigned:
2631 return static_cast<T
>(m_value.number_unsigned);
2634 case value_t::number_float:
2636 return static_cast<T
>(m_value.number_float);
2641 throw std::domain_error(
"type must be number, but is " + type_name());
2651 :
throw std::domain_error(
"type must be boolean, but is " + type_name());
2657 return is_object() ? m_value.object :
nullptr;
2663 return is_object() ? m_value.object :
nullptr;
2669 return is_array() ? m_value.array :
nullptr;
2673 constexpr
const array_t* get_impl_ptr(
const array_t*)
const noexcept
2675 return is_array() ? m_value.array :
nullptr;
2681 return is_string() ? m_value.string :
nullptr;
2687 return is_string() ? m_value.string :
nullptr;
2693 return is_boolean() ? &m_value.boolean :
nullptr;
2699 return is_boolean() ? &m_value.boolean :
nullptr;
2705 return is_number_integer() ? &m_value.number_integer :
nullptr;
2711 return is_number_integer() ? &m_value.number_integer :
nullptr;
2717 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2723 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2729 return is_number_float() ? &m_value.number_float :
nullptr;
2735 return is_number_float() ? &m_value.number_float :
nullptr;
2749 template<
typename ReferenceType,
typename ThisType>
2750 static ReferenceType get_ref_impl(ThisType& obj)
2753 using PointerType =
typename std::add_pointer<ReferenceType>::type;
2754 auto ptr = obj.template get_ptr<PointerType>();
2762 throw std::domain_error(
"incompatible ReferenceType for get_ref, actual type is " +
2805 template<
typename ValueType,
typename 2807 not std::is_pointer<ValueType>::value
2809 ValueType
get()
const 2811 return get_impl(static_cast<ValueType*>(
nullptr));
2840 template<
typename PointerType,
typename 2842 std::is_pointer<PointerType>::value
2844 PointerType
get() noexcept
2847 return get_ptr<PointerType>();
2854 template<
typename PointerType,
typename 2856 std::is_pointer<PointerType>::value
2858 constexpr
const PointerType
get()
const noexcept
2861 return get_ptr<PointerType>();
2889 template<
typename PointerType,
typename 2891 std::is_pointer<PointerType>::value
2896 return get_impl_ptr(static_cast<PointerType>(
nullptr));
2903 template<
typename PointerType,
typename 2905 std::is_pointer<PointerType>::value
2906 and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2908 constexpr
const PointerType
get_ptr() const noexcept
2911 return get_impl_ptr(static_cast<const PointerType>(
nullptr));
2940 template<
typename ReferenceType,
typename 2942 std::is_reference<ReferenceType>::value
2947 return get_ref_impl<ReferenceType>(*this);
2954 template<
typename ReferenceType,
typename 2956 std::is_reference<ReferenceType>::value
2957 and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
2962 return get_ref_impl<ReferenceType>(*this);
2993 template <
typename ValueType,
typename 2995 not std::is_pointer<ValueType>::value
2996 and not std::is_same<ValueType, typename string_t::value_type>::value
2997 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015 2998 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3001 operator ValueType()
const 3004 return get<ValueType>();
3046 assert(m_value.array !=
nullptr);
3047 return m_value.array->at(idx);
3049 catch (std::out_of_range&)
3052 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3057 throw std::domain_error(
"cannot use at() with " + type_name());
3090 assert(m_value.array !=
nullptr);
3091 return m_value.array->at(idx);
3093 catch (std::out_of_range&)
3096 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3101 throw std::domain_error(
"cannot use at() with " + type_name());
3138 assert(m_value.object !=
nullptr);
3139 return m_value.object->at(key);
3141 catch (std::out_of_range&)
3144 throw std::out_of_range(
"key '" + key +
"' not found");
3149 throw std::domain_error(
"cannot use at() with " + type_name());
3186 assert(m_value.object !=
nullptr);
3187 return m_value.object->at(key);
3189 catch (std::out_of_range&)
3192 throw std::out_of_range(
"key '" + key +
"' not found");
3197 throw std::domain_error(
"cannot use at() with " + type_name());
3231 m_type = value_t::array;
3232 m_value.
array = create<array_t>();
3239 assert(m_value.array !=
nullptr);
3240 for (
size_t i = m_value.array->size(); i <= idx; ++i)
3242 m_value.array->push_back(basic_json());
3245 return m_value.array->operator[](idx);
3249 throw std::domain_error(
"cannot use operator[] with " + type_name());
3277 assert(m_value.array !=
nullptr);
3278 return m_value.array->operator[](idx);
3282 throw std::domain_error(
"cannot use operator[] with " + type_name());
3318 m_type = value_t::object;
3319 m_value.
object = create<object_t>();
3325 assert(m_value.object !=
nullptr);
3326 return m_value.object->operator[](key);
3330 throw std::domain_error(
"cannot use operator[] with " + type_name());
3366 assert(m_value.object !=
nullptr);
3367 assert(m_value.object->find(key) != m_value.object->end());
3368 return m_value.object->find(key)->second;
3372 throw std::domain_error(
"cannot use operator[] with " + type_name());
3403 template<
typename T, std::
size_t n>
3406 return operator[](static_cast<const T>(key));
3438 template<
typename T, std::
size_t n>
3441 return operator[](static_cast<const T>(key));
3471 template<
typename T>
3477 m_type = value_t::object;
3478 m_value = value_t::object;
3484 assert(m_value.object !=
nullptr);
3485 return m_value.object->operator[](key);
3489 throw std::domain_error(
"cannot use operator[] with " + type_name());
3520 template<
typename T>
3526 assert(m_value.object !=
nullptr);
3527 assert(m_value.object->find(key) != m_value.object->end());
3528 return m_value.object->find(key)->second;
3532 throw std::domain_error(
"cannot use operator[] with " + type_name());
3584 template <
class ValueType,
typename 3586 std::is_convertible<basic_json_t, ValueType>::value
3588 ValueType
value(
const typename object_t::key_type& key, ValueType default_value)
const 3594 const auto it = find(key);
3601 return default_value;
3606 throw std::domain_error(
"cannot use value() with " + type_name());
3614 string_t value(
const typename object_t::key_type& key,
const char* default_value)
const 3616 return value(key,
string_t(default_value));
3747 template <
class InteratorType,
typename 3749 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3750 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3756 if (
this != pos.m_object)
3758 throw std::domain_error(
"iterator does not fit current value");
3761 InteratorType result = end();
3765 case value_t::boolean:
3766 case value_t::number_float:
3767 case value_t::number_integer:
3768 case value_t::number_unsigned:
3769 case value_t::string:
3771 if (not pos.m_it.primitive_iterator.is_begin())
3773 throw std::out_of_range(
"iterator out of range");
3778 delete m_value.string;
3779 m_value.string =
nullptr;
3782 m_type = value_t::null;
3786 case value_t::object:
3788 assert(m_value.object !=
nullptr);
3789 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3793 case value_t::array:
3795 assert(m_value.array !=
nullptr);
3796 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3802 throw std::domain_error(
"cannot use erase() with " + type_name());
3855 template <
class InteratorType,
typename 3857 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3858 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3861 InteratorType
erase(InteratorType first, InteratorType last)
3864 if (
this != first.m_object or
this != last.m_object)
3866 throw std::domain_error(
"iterators do not fit current value");
3869 InteratorType result = end();
3873 case value_t::boolean:
3874 case value_t::number_float:
3875 case value_t::number_integer:
3876 case value_t::number_unsigned:
3877 case value_t::string:
3879 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3881 throw std::out_of_range(
"iterators out of range");
3886 delete m_value.string;
3887 m_value.string =
nullptr;
3890 m_type = value_t::null;
3894 case value_t::object:
3896 assert(m_value.object !=
nullptr);
3897 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3898 last.m_it.object_iterator);
3902 case value_t::array:
3904 assert(m_value.array !=
nullptr);
3905 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3906 last.m_it.array_iterator);
3912 throw std::domain_error(
"cannot use erase() with " + type_name());
3953 assert(m_value.object !=
nullptr);
3954 return m_value.object->erase(key);
3958 throw std::domain_error(
"cannot use erase() with " + type_name());
3993 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3996 assert(m_value.array !=
nullptr);
3997 m_value.array->erase(m_value.array->begin() +
static_cast<difference_type>(idx));
4001 throw std::domain_error(
"cannot use erase() with " + type_name());
4035 auto result = end();
4039 assert(m_value.object !=
nullptr);
4040 result.m_it.object_iterator = m_value.object->find(key);
4052 auto result = cend();
4056 assert(m_value.object !=
nullptr);
4057 result.m_it.object_iterator = m_value.object->find(key);
4084 assert(not is_object() or m_value.object !=
nullptr);
4085 return is_object() ? m_value.object->count(key) : 0;
4373 template<
typename IteratorType>
class iteration_proxy;
4389 return iteration_proxy<iterator>(cont);
4397 return iteration_proxy<const_iterator>(cont);
4453 case value_t::array:
4455 assert(m_value.array !=
nullptr);
4456 return m_value.array->empty();
4459 case value_t::object:
4461 assert(m_value.object !=
nullptr);
4462 return m_value.object->empty();
4517 case value_t::array:
4519 assert(m_value.array !=
nullptr);
4520 return m_value.array->size();
4523 case value_t::object:
4525 assert(m_value.object !=
nullptr);
4526 return m_value.object->size();
4577 case value_t::array:
4579 assert(m_value.array !=
nullptr);
4580 return m_value.array->max_size();
4583 case value_t::object:
4585 assert(m_value.object !=
nullptr);
4586 return m_value.object->max_size();
4636 case value_t::number_integer:
4638 m_value.number_integer = 0;
4642 case value_t::number_unsigned:
4644 m_value.number_unsigned = 0;
4648 case value_t::number_float:
4650 m_value.number_float = 0.0;
4654 case value_t::boolean:
4656 m_value.boolean =
false;
4660 case value_t::string:
4662 assert(m_value.string !=
nullptr);
4663 m_value.string->clear();
4667 case value_t::array:
4669 assert(m_value.array !=
nullptr);
4670 m_value.array->clear();
4674 case value_t::object:
4676 assert(m_value.object !=
nullptr);
4677 m_value.object->clear();
4711 if (not(is_null() or is_array()))
4713 throw std::domain_error(
"cannot use push_back() with " + type_name());
4719 m_type = value_t::array;
4720 m_value = value_t::array;
4724 assert(m_value.array !=
nullptr);
4725 m_value.array->push_back(std::move(val));
4727 val.m_type = value_t::null;
4736 push_back(std::move(val));
4747 if (not(is_null() or is_array()))
4749 throw std::domain_error(
"cannot use push_back() with " + type_name());
4755 m_type = value_t::array;
4756 m_value = value_t::array;
4760 assert(m_value.array !=
nullptr);
4761 m_value.array->push_back(val);
4797 if (not(is_null() or is_object()))
4799 throw std::domain_error(
"cannot use push_back() with " + type_name());
4805 m_type = value_t::object;
4806 m_value = value_t::object;
4810 assert(m_value.object !=
nullptr);
4811 m_value.object->insert(val);
4851 if (is_object() and init.size() == 2 and init.begin()->is_string())
4853 const string_t key = *init.begin();
4854 push_back(
typename object_t::value_type(key, *(init.begin() + 1)));
4858 push_back(basic_json(init));
4900 if (pos.m_object !=
this)
4902 throw std::domain_error(
"iterator does not fit current value");
4907 assert(m_value.array !=
nullptr);
4908 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4913 throw std::domain_error(
"cannot use insert() with " + type_name());
4923 return insert(pos, val);
4956 if (pos.m_object !=
this)
4958 throw std::domain_error(
"iterator does not fit current value");
4963 assert(m_value.array !=
nullptr);
4964 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4969 throw std::domain_error(
"cannot use insert() with " + type_name());
5008 throw std::domain_error(
"cannot use insert() with " + type_name());
5012 if (pos.m_object !=
this)
5014 throw std::domain_error(
"iterator does not fit current value");
5018 if (first.m_object != last.m_object)
5020 throw std::domain_error(
"iterators do not fit");
5023 if (first.m_object ==
this or last.m_object ==
this)
5025 throw std::domain_error(
"passed iterators may not belong to container");
5030 assert(m_value.array !=
nullptr);
5031 result.m_it.array_iterator = m_value.array->insert(
5032 pos.m_it.array_iterator,
5033 first.m_it.array_iterator,
5034 last.m_it.array_iterator);
5067 throw std::domain_error(
"cannot use insert() with " + type_name());
5071 if (pos.m_object !=
this)
5073 throw std::domain_error(
"iterator does not fit current value");
5078 assert(m_value.array !=
nullptr);
5079 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5101 std::is_nothrow_move_constructible<value_t>::value and
5102 std::is_nothrow_move_assignable<value_t>::value and
5103 std::is_nothrow_move_constructible<json_value>::value and
5104 std::is_nothrow_move_assignable<json_value>::value
5107 std::swap(m_type, other.m_type);
5108 std::swap(m_value, other.m_value);
5136 assert(m_value.array !=
nullptr);
5137 std::swap(*(m_value.array), other);
5141 throw std::domain_error(
"cannot use swap() with " + type_name());
5170 assert(m_value.object !=
nullptr);
5171 std::swap(*(m_value.object), other);
5175 throw std::domain_error(
"cannot use swap() with " + type_name());
5204 assert(m_value.string !=
nullptr);
5205 std::swap(*(m_value.string), other);
5209 throw std::domain_error(
"cannot use swap() with " + type_name());
5235 static constexpr std::array<uint8_t, 8> order = {{
5248 if (lhs == value_t::discarded or rhs == value_t::discarded)
5253 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
5282 const auto lhs_type = lhs.type();
5283 const auto rhs_type = rhs.type();
5285 if (lhs_type == rhs_type)
5289 case value_t::array:
5291 assert(lhs.m_value.array !=
nullptr);
5292 assert(rhs.m_value.array !=
nullptr);
5293 return *lhs.m_value.array == *rhs.m_value.array;
5295 case value_t::object:
5297 assert(lhs.m_value.object !=
nullptr);
5298 assert(rhs.m_value.object !=
nullptr);
5299 return *lhs.m_value.object == *rhs.m_value.object;
5305 case value_t::string:
5307 assert(lhs.m_value.string !=
nullptr);
5308 assert(rhs.m_value.string !=
nullptr);
5309 return *lhs.m_value.string == *rhs.m_value.string;
5311 case value_t::boolean:
5313 return lhs.m_value.boolean == rhs.m_value.boolean;
5315 case value_t::number_integer:
5317 return lhs.m_value.number_integer == rhs.m_value.number_integer;
5319 case value_t::number_unsigned:
5321 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5323 case value_t::number_float:
5325 return lhs.m_value.number_float == rhs.m_value.number_float;
5333 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5335 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5337 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5339 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_integer);
5341 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5343 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5345 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5347 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5349 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5351 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5353 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5355 return lhs.m_value.number_integer ==
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5411 return not (lhs == rhs);
5443 return not v.is_null();
5472 const auto lhs_type = lhs.type();
5473 const auto rhs_type = rhs.type();
5475 if (lhs_type == rhs_type)
5479 case value_t::array:
5481 assert(lhs.m_value.array !=
nullptr);
5482 assert(rhs.m_value.array !=
nullptr);
5483 return *lhs.m_value.array < *rhs.m_value.array;
5485 case value_t::object:
5487 assert(lhs.m_value.object !=
nullptr);
5488 assert(rhs.m_value.object !=
nullptr);
5489 return *lhs.m_value.object < *rhs.m_value.object;
5495 case value_t::string:
5497 assert(lhs.m_value.string !=
nullptr);
5498 assert(rhs.m_value.string !=
nullptr);
5499 return *lhs.m_value.string < *rhs.m_value.string;
5501 case value_t::boolean:
5503 return lhs.m_value.boolean < rhs.m_value.boolean;
5505 case value_t::number_integer:
5507 return lhs.m_value.number_integer < rhs.m_value.number_integer;
5509 case value_t::number_unsigned:
5511 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5513 case value_t::number_float:
5515 return lhs.m_value.number_float < rhs.m_value.number_float;
5523 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5525 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5527 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5529 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_integer);
5531 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5533 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5535 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5537 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5539 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5541 return lhs.m_value.number_integer <
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5543 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5545 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5551 return operator<(lhs_type, rhs_type);
5573 return not (rhs < lhs);
5595 return not (lhs <= rhs);
5617 return not (lhs < rhs);
5652 friend std::ostream&
operator<<(std::ostream& o,
const basic_json& j)
5655 const bool pretty_print = (o.width() > 0);
5656 const auto indentation = (pretty_print ? o.width() : 0);
5661 auto old_locale = o.imbue(std::locale(std::locale(),
new DecimalSeparator));
5664 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
5667 o.imbue(old_locale);
5675 friend std::ostream&
operator>>(
const basic_json& j, std::ostream& o)
5716 return parser(s, cb).
parse();
5745 return parser(i, cb).
parse();
5753 return parser(i, cb).
parse();
5781 j = parser(i).
parse();
5791 j = parser(i).
parse();
5804 string_t type_name()
const noexcept
5810 case value_t::object:
5812 case value_t::array:
5814 case value_t::string:
5816 case value_t::boolean:
5818 case value_t::discarded:
5833 static std::size_t extra_space(
const string_t& s) noexcept
5835 std::size_t result = 0;
5837 for (
const auto& c : s)
5856 if (c >= 0x00 and c <= 0x1f)
5884 const auto space = extra_space(s);
5891 string_t result(s.size() + space,
'\\');
5892 std::size_t pos = 0;
5894 for (
const auto& c : s)
5901 result[pos + 1] =
'"';
5917 result[pos + 1] =
'b';
5925 result[pos + 1] =
'f';
5933 result[pos + 1] =
'n';
5941 result[pos + 1] =
'r';
5949 result[pos + 1] =
't';
5956 if (c >= 0x00 and c <= 0x1f)
5960 const auto hexify = [](
const int v) ->
char 5963 ? (
'0' +
static_cast<char>(v))
5964 : (
'a' +
static_cast<char>((v - 10) & 0x1f));
5969 {
'u',
'0',
'0', hexify(c >> 4), hexify(c & 0x0f)
6007 void dump(std::ostream& o,
6008 const bool pretty_print,
6009 const unsigned int indent_step,
6010 const unsigned int current_indent = 0)
const 6013 unsigned int new_indent = current_indent;
6017 case value_t::object:
6019 assert(m_value.object !=
nullptr);
6021 if (m_value.object->empty())
6032 new_indent += indent_step;
6036 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
6038 if (i != m_value.object->cbegin())
6040 o << (pretty_print ?
",\n" :
",");
6042 o <<
string_t(new_indent,
' ') <<
"\"" 6043 << escape_string(i->first) <<
"\":" 6044 << (pretty_print ?
" " :
"");
6045 i->second.dump(o, pretty_print, indent_step, new_indent);
6051 new_indent -= indent_step;
6055 o <<
string_t(new_indent,
' ') +
"}";
6059 case value_t::array:
6061 assert(m_value.array !=
nullptr);
6063 if (m_value.array->empty())
6074 new_indent += indent_step;
6078 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6080 if (i != m_value.array->cbegin())
6082 o << (pretty_print ?
",\n" :
",");
6085 i->dump(o, pretty_print, indent_step, new_indent);
6091 new_indent -= indent_step;
6095 o <<
string_t(new_indent,
' ') <<
"]";
6099 case value_t::string:
6101 assert(m_value.string !=
nullptr);
6102 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
6106 case value_t::boolean:
6108 o << (m_value.boolean ?
"true" :
"false");
6112 case value_t::number_integer:
6114 o << m_value.number_integer;
6118 case value_t::number_unsigned:
6120 o << m_value.number_unsigned;
6124 case value_t::number_float:
6126 if (m_value.number_float == 0)
6129 o << (std::signbit(m_value.number_float) ?
"-0.0" :
"0.0");
6138 o << std::setprecision(std::numeric_limits<double>::digits10)
6139 << m_value.number_float;
6144 case value_t::discarded:
6164 value_t m_type = value_t::null;
6167 json_value m_value = {};
6184 class primitive_iterator_t
6188 void set_begin() noexcept
6194 void set_end() noexcept
6200 constexpr
bool is_begin()
const noexcept
6202 return (m_it == begin_value);
6206 constexpr
bool is_end()
const noexcept
6208 return (m_it == end_value);
6228 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6238 struct internal_iterator
6241 typename object_t::iterator object_iterator;
6243 typename array_t::iterator array_iterator;
6245 primitive_iterator_t primitive_iterator;
6248 internal_iterator() noexcept
6249 : object_iterator(), array_iterator(), primitive_iterator()
6254 template<
typename IteratorType>
6255 class iteration_proxy
6259 class iteration_proxy_internal
6263 IteratorType anchor;
6265 size_t array_index = 0;
6268 explicit iteration_proxy_internal(IteratorType it) noexcept
6273 iteration_proxy_internal& operator*()
6279 iteration_proxy_internal& operator++()
6288 bool operator!= (
const iteration_proxy_internal& o)
const 6290 return anchor != o.anchor;
6296 assert(anchor.m_object !=
nullptr);
6298 switch (anchor.m_object->type())
6301 case value_t::array:
6303 return std::to_string(array_index);
6307 case value_t::object:
6309 return anchor.key();
6321 typename IteratorType::reference value()
const 6323 return anchor.value();
6328 typename IteratorType::reference container;
6332 explicit iteration_proxy(
typename IteratorType::reference cont)
6337 iteration_proxy_internal begin() noexcept
6339 return iteration_proxy_internal(container.begin());
6343 iteration_proxy_internal end() noexcept
6345 return iteration_proxy_internal(container.end());
6363 class const_iterator :
public std::iterator<std::random_access_iterator_tag, const basic_json>
6366 friend class basic_json;
6387 assert(m_object !=
nullptr);
6389 switch (m_object->m_type)
6393 m_it.object_iterator =
typename object_t::iterator();
6399 m_it.array_iterator =
typename array_t::iterator();
6405 m_it.primitive_iterator = primitive_iterator_t();
6413 : m_object(other.m_object)
6415 assert(m_object !=
nullptr);
6417 switch (m_object->m_type)
6421 m_it.object_iterator = other.m_it.object_iterator;
6427 m_it.array_iterator = other.m_it.array_iterator;
6433 m_it.primitive_iterator = other.m_it.primitive_iterator;
6441 : m_object(other.m_object), m_it(other.m_it)
6446 std::is_nothrow_move_constructible<pointer>::value and
6447 std::is_nothrow_move_assignable<pointer>::value and
6448 std::is_nothrow_move_constructible<internal_iterator>::value and
6449 std::is_nothrow_move_assignable<internal_iterator>::value
6452 std::swap(m_object, other.m_object);
6453 std::swap(m_it, other.m_it);
6459 void set_begin() noexcept
6461 assert(m_object !=
nullptr);
6463 switch (m_object->m_type)
6467 assert(m_object->m_value.object !=
nullptr);
6468 m_it.object_iterator = m_object->m_value.object->begin();
6474 assert(m_object->m_value.array !=
nullptr);
6475 m_it.array_iterator = m_object->m_value.array->begin();
6482 m_it.primitive_iterator.set_end();
6488 m_it.primitive_iterator.set_begin();
6495 void set_end() noexcept
6497 assert(m_object !=
nullptr);
6499 switch (m_object->m_type)
6503 assert(m_object->m_value.object !=
nullptr);
6504 m_it.object_iterator = m_object->m_value.object->end();
6510 assert(m_object->m_value.array !=
nullptr);
6511 m_it.array_iterator = m_object->m_value.array->end();
6517 m_it.primitive_iterator.set_end();
6527 assert(m_object !=
nullptr);
6529 switch (m_object->m_type)
6533 assert(m_object->m_value.object);
6534 assert(m_it.object_iterator != m_object->m_value.object->end());
6535 return m_it.object_iterator->second;
6540 assert(m_object->m_value.array);
6541 assert(m_it.array_iterator != m_object->m_value.array->end());
6542 return *m_it.array_iterator;
6547 throw std::out_of_range(
"cannot get value");
6552 if (m_it.primitive_iterator.is_begin())
6558 throw std::out_of_range(
"cannot get value");
6567 assert(m_object !=
nullptr);
6569 switch (m_object->m_type)
6573 assert(m_object->m_value.object);
6574 assert(m_it.object_iterator != m_object->m_value.object->end());
6575 return &(m_it.object_iterator->second);
6580 assert(m_object->m_value.array);
6581 assert(m_it.array_iterator != m_object->m_value.array->end());
6582 return &*m_it.array_iterator;
6587 if (m_it.primitive_iterator.is_begin())
6593 throw std::out_of_range(
"cannot get value");
6602 auto result = *
this;
6610 assert(m_object !=
nullptr);
6612 switch (m_object->m_type)
6616 ++m_it.object_iterator;
6622 ++m_it.array_iterator;
6628 ++m_it.primitive_iterator;
6639 auto result = *
this;
6647 assert(m_object !=
nullptr);
6649 switch (m_object->m_type)
6653 --m_it.object_iterator;
6659 --m_it.array_iterator;
6665 --m_it.primitive_iterator;
6677 if (m_object != other.m_object)
6679 throw std::domain_error(
"cannot compare iterators of different containers");
6682 assert(m_object !=
nullptr);
6684 switch (m_object->m_type)
6688 return (m_it.object_iterator == other.m_it.object_iterator);
6693 return (m_it.array_iterator == other.m_it.array_iterator);
6698 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6706 return not operator==(other);
6713 if (m_object != other.m_object)
6715 throw std::domain_error(
"cannot compare iterators of different containers");
6718 assert(m_object !=
nullptr);
6720 switch (m_object->m_type)
6724 throw std::domain_error(
"cannot compare order of object iterators");
6729 return (m_it.array_iterator < other.m_it.array_iterator);
6734 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6742 return not other.operator < (*this);
6748 return not operator<=(other);
6754 return not operator<(other);
6760 assert(m_object !=
nullptr);
6762 switch (m_object->m_type)
6766 throw std::domain_error(
"cannot use offsets with object iterators");
6771 m_it.array_iterator += i;
6777 m_it.primitive_iterator += i;
6788 return operator+=(-i);
6794 auto result = *
this;
6802 auto result = *
this;
6810 assert(m_object !=
nullptr);
6812 switch (m_object->m_type)
6816 throw std::domain_error(
"cannot use offsets with object iterators");
6821 return m_it.array_iterator - other.m_it.array_iterator;
6826 return m_it.primitive_iterator - other.m_it.primitive_iterator;
6834 assert(m_object !=
nullptr);
6836 switch (m_object->m_type)
6840 throw std::domain_error(
"cannot use operator[] for object iterators");
6845 return *(m_it.array_iterator + n);
6850 throw std::out_of_range(
"cannot get value");
6855 if (m_it.primitive_iterator == -n)
6861 throw std::out_of_range(
"cannot get value");
6868 typename object_t::key_type
key()
const 6870 assert(m_object !=
nullptr);
6872 if (m_object->is_object())
6874 return m_it.object_iterator->first;
6878 throw std::domain_error(
"cannot use key() for non-object iterators");
6892 internal_iterator m_it = internal_iterator();
6929 std::is_nothrow_move_constructible<pointer>::value and
6930 std::is_nothrow_move_assignable<pointer>::value and
6931 std::is_nothrow_move_constructible<internal_iterator>::value and
6932 std::is_nothrow_move_assignable<internal_iterator>::value
6935 base_iterator::operator=(other);
6942 return const_cast<reference>(base_iterator::operator*());
6948 return const_cast<pointer>(base_iterator::operator->());
6955 base_iterator::operator++();
6962 base_iterator::operator++();
6970 base_iterator::operator--();
6977 base_iterator::operator--();
6984 base_iterator::operator+=(i);
6991 base_iterator::operator-=(i);
6998 auto result = *
this;
7006 auto result = *
this;
7014 return base_iterator::operator-(other);
7020 return const_cast<reference>(base_iterator::operator[](n));
7026 return const_cast<reference>(base_iterator::value());
7047 template<
typename Base>
7069 return base_iterator::operator++(1);
7075 base_iterator::operator++();
7082 return base_iterator::operator--(1);
7088 base_iterator::operator--();
7095 base_iterator::operator+=(i);
7102 auto result = *
this;
7110 auto result = *
this;
7118 return this->base() - other.base();
7124 return *(this->operator+(n));
7128 typename object_t::key_type
key()
const 7130 auto it = --this->base();
7137 auto it = --this->base();
7138 return it.operator * ();
7159 enum class token_type
7178 using lexer_char_t =
unsigned char;
7181 explicit lexer(
const string_t& s) noexcept
7182 : m_stream(
nullptr), m_buffer(s)
7184 m_content =
reinterpret_cast<const lexer_char_t*
>(s.c_str());
7185 assert(m_content !=
nullptr);
7186 m_start = m_cursor = m_content;
7187 m_limit = m_content + s.size();
7191 explicit lexer(std::istream* s) noexcept
7192 : m_stream(s), m_buffer()
7194 assert(m_stream !=
nullptr);
7195 getline(*m_stream, m_buffer);
7196 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
7197 assert(m_content !=
nullptr);
7198 m_start = m_cursor = m_content;
7199 m_limit = m_content + m_buffer.size();
7206 lexer(
const lexer&) =
delete;
7207 lexer operator=(
const lexer&) =
delete;
7224 static string_t to_unicode(
const std::size_t codepoint1,
7225 const std::size_t codepoint2 = 0)
7228 std::size_t codepoint = codepoint1;
7231 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7234 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7248 throw std::invalid_argument(
"missing or wrong low surrogate");
7254 if (codepoint < 0x80)
7257 result.append(1, static_cast<typename string_t::value_type>(codepoint));
7259 else if (codepoint <= 0x7ff)
7262 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7263 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7265 else if (codepoint <= 0xffff)
7268 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7269 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7270 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7272 else if (codepoint <= 0x10ffff)
7275 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7276 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7277 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7278 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7282 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
7289 static std::string token_type_name(token_type t)
7293 case token_type::uninitialized:
7294 return "<uninitialized>";
7295 case token_type::literal_true:
7296 return "true literal";
7297 case token_type::literal_false:
7298 return "false literal";
7299 case token_type::literal_null:
7300 return "null literal";
7301 case token_type::value_string:
7302 return "string literal";
7303 case token_type::value_number:
7304 return "number literal";
7305 case token_type::begin_array:
7307 case token_type::begin_object:
7309 case token_type::end_array:
7311 case token_type::end_object:
7313 case token_type::name_separator:
7315 case token_type::value_separator:
7317 case token_type::parse_error:
7318 return "<parse error>";
7319 case token_type::end_of_input:
7320 return "end of input";
7324 return "unknown token";
7339 token_type scan() noexcept
7346 assert(m_start !=
nullptr);
7351 unsigned int yyaccept = 0;
7352 static const unsigned char yybm[] =
7354 0, 0, 0, 0, 0, 0, 0, 0,
7355 0, 32, 32, 0, 0, 32, 0, 0,
7356 128, 128, 128, 128, 128, 128, 128, 128,
7357 128, 128, 128, 128, 128, 128, 128, 128,
7358 160, 128, 0, 128, 128, 128, 128, 128,
7359 128, 128, 128, 128, 128, 128, 128, 128,
7360 192, 192, 192, 192, 192, 192, 192, 192,
7361 192, 192, 128, 128, 128, 128, 128, 128,
7362 128, 128, 128, 128, 128, 128, 128, 128,
7363 128, 128, 128, 128, 128, 128, 128, 128,
7364 128, 128, 128, 128, 128, 128, 128, 128,
7365 128, 128, 128, 128, 0, 128, 128, 128,
7366 128, 128, 128, 128, 128, 128, 128, 128,
7367 128, 128, 128, 128, 128, 128, 128, 128,
7368 128, 128, 128, 128, 128, 128, 128, 128,
7369 128, 128, 128, 128, 128, 128, 128, 128,
7370 128, 128, 128, 128, 128, 128, 128, 128,
7371 128, 128, 128, 128, 128, 128, 128, 128,
7372 128, 128, 128, 128, 128, 128, 128, 128,
7373 128, 128, 128, 128, 128, 128, 128, 128,
7374 128, 128, 128, 128, 128, 128, 128, 128,
7375 128, 128, 128, 128, 128, 128, 128, 128,
7376 128, 128, 128, 128, 128, 128, 128, 128,
7377 128, 128, 128, 128, 128, 128, 128, 128,
7378 128, 128, 128, 128, 128, 128, 128, 128,
7379 128, 128, 128, 128, 128, 128, 128, 128,
7380 128, 128, 128, 128, 128, 128, 128, 128,
7381 128, 128, 128, 128, 128, 128, 128, 128,
7382 128, 128, 128, 128, 128, 128, 128, 128,
7383 128, 128, 128, 128, 128, 128, 128, 128,
7384 128, 128, 128, 128, 128, 128, 128, 128,
7385 128, 128, 128, 128, 128, 128, 128, 128,
7387 if ((m_limit - m_cursor) < 5)
7392 if (yybm[0 + yych] & 32)
7394 goto basic_json_parser_6;
7404 goto basic_json_parser_2;
7408 goto basic_json_parser_4;
7410 goto basic_json_parser_9;
7416 goto basic_json_parser_4;
7420 goto basic_json_parser_10;
7422 goto basic_json_parser_12;
7431 goto basic_json_parser_4;
7435 goto basic_json_parser_13;
7437 goto basic_json_parser_15;
7443 goto basic_json_parser_17;
7447 goto basic_json_parser_19;
7449 goto basic_json_parser_4;
7461 goto basic_json_parser_21;
7465 goto basic_json_parser_4;
7467 goto basic_json_parser_23;
7473 goto basic_json_parser_24;
7477 goto basic_json_parser_4;
7479 goto basic_json_parser_25;
7488 goto basic_json_parser_26;
7490 goto basic_json_parser_4;
7496 goto basic_json_parser_28;
7500 goto basic_json_parser_30;
7502 goto basic_json_parser_4;
7506 basic_json_parser_2:
7509 return token_type::end_of_input;
7511 basic_json_parser_4:
7513 basic_json_parser_5:
7515 return token_type::parse_error;
7517 basic_json_parser_6:
7519 if (m_limit <= m_cursor)
7524 if (yybm[0 + yych] & 32)
7526 goto basic_json_parser_6;
7531 basic_json_parser_9:
7533 yych = *(m_marker = ++m_cursor);
7536 goto basic_json_parser_5;
7538 goto basic_json_parser_32;
7539 basic_json_parser_10:
7542 return token_type::value_separator;
7544 basic_json_parser_12:
7548 goto basic_json_parser_5;
7552 goto basic_json_parser_13;
7556 goto basic_json_parser_15;
7558 goto basic_json_parser_5;
7559 basic_json_parser_13:
7561 yych = *(m_marker = ++m_cursor);
7566 goto basic_json_parser_37;
7573 goto basic_json_parser_38;
7577 goto basic_json_parser_38;
7580 basic_json_parser_14:
7582 return token_type::value_number;
7584 basic_json_parser_15:
7586 m_marker = ++m_cursor;
7587 if ((m_limit - m_cursor) < 3)
7592 if (yybm[0 + yych] & 64)
7594 goto basic_json_parser_15;
7600 goto basic_json_parser_37;
7602 goto basic_json_parser_14;
7608 goto basic_json_parser_38;
7612 goto basic_json_parser_38;
7614 goto basic_json_parser_14;
7616 basic_json_parser_17:
7619 return token_type::name_separator;
7621 basic_json_parser_19:
7624 return token_type::begin_array;
7626 basic_json_parser_21:
7629 return token_type::end_array;
7631 basic_json_parser_23:
7633 yych = *(m_marker = ++m_cursor);
7636 goto basic_json_parser_39;
7638 goto basic_json_parser_5;
7639 basic_json_parser_24:
7641 yych = *(m_marker = ++m_cursor);
7644 goto basic_json_parser_40;
7646 goto basic_json_parser_5;
7647 basic_json_parser_25:
7649 yych = *(m_marker = ++m_cursor);
7652 goto basic_json_parser_41;
7654 goto basic_json_parser_5;
7655 basic_json_parser_26:
7658 return token_type::begin_object;
7660 basic_json_parser_28:
7663 return token_type::end_object;
7665 basic_json_parser_30:
7667 yych = *(m_marker = ++m_cursor);
7670 goto basic_json_parser_42;
7672 goto basic_json_parser_5;
7673 basic_json_parser_31:
7675 if (m_limit <= m_cursor)
7680 basic_json_parser_32:
7681 if (yybm[0 + yych] & 128)
7683 goto basic_json_parser_31;
7687 goto basic_json_parser_33;
7691 goto basic_json_parser_34;
7693 goto basic_json_parser_36;
7694 basic_json_parser_33:
7695 m_cursor = m_marker;
7698 goto basic_json_parser_5;
7702 goto basic_json_parser_14;
7704 basic_json_parser_34:
7707 return token_type::value_string;
7709 basic_json_parser_36:
7711 if (m_limit <= m_cursor)
7722 goto basic_json_parser_31;
7726 goto basic_json_parser_33;
7728 goto basic_json_parser_31;
7736 goto basic_json_parser_33;
7738 goto basic_json_parser_31;
7744 goto basic_json_parser_31;
7746 goto basic_json_parser_33;
7756 goto basic_json_parser_31;
7760 goto basic_json_parser_31;
7762 goto basic_json_parser_33;
7770 goto basic_json_parser_31;
7772 goto basic_json_parser_33;
7778 goto basic_json_parser_31;
7782 goto basic_json_parser_43;
7784 goto basic_json_parser_33;
7788 basic_json_parser_37:
7792 goto basic_json_parser_33;
7796 goto basic_json_parser_44;
7798 goto basic_json_parser_33;
7799 basic_json_parser_38:
7805 goto basic_json_parser_46;
7807 goto basic_json_parser_33;
7813 goto basic_json_parser_46;
7817 goto basic_json_parser_33;
7821 goto basic_json_parser_47;
7823 goto basic_json_parser_33;
7825 basic_json_parser_39:
7829 goto basic_json_parser_49;
7831 goto basic_json_parser_33;
7832 basic_json_parser_40:
7836 goto basic_json_parser_50;
7838 goto basic_json_parser_33;
7839 basic_json_parser_41:
7843 goto basic_json_parser_51;
7845 goto basic_json_parser_33;
7846 basic_json_parser_42:
7850 goto basic_json_parser_52;
7852 goto basic_json_parser_33;
7853 basic_json_parser_43:
7855 if (m_limit <= m_cursor)
7864 goto basic_json_parser_33;
7868 goto basic_json_parser_54;
7870 goto basic_json_parser_33;
7876 goto basic_json_parser_54;
7880 goto basic_json_parser_33;
7884 goto basic_json_parser_54;
7886 goto basic_json_parser_33;
7888 basic_json_parser_44:
7890 m_marker = ++m_cursor;
7891 if ((m_limit - m_cursor) < 3)
7900 goto basic_json_parser_14;
7904 goto basic_json_parser_44;
7906 goto basic_json_parser_14;
7912 goto basic_json_parser_38;
7916 goto basic_json_parser_38;
7918 goto basic_json_parser_14;
7920 basic_json_parser_46:
7924 goto basic_json_parser_33;
7928 goto basic_json_parser_33;
7930 basic_json_parser_47:
7932 if (m_limit <= m_cursor)
7939 goto basic_json_parser_14;
7943 goto basic_json_parser_47;
7945 goto basic_json_parser_14;
7946 basic_json_parser_49:
7950 goto basic_json_parser_55;
7952 goto basic_json_parser_33;
7953 basic_json_parser_50:
7957 goto basic_json_parser_56;
7959 goto basic_json_parser_33;
7960 basic_json_parser_51:
7964 goto basic_json_parser_58;
7966 goto basic_json_parser_33;
7967 basic_json_parser_52:
7972 basic_json_parser_54:
7974 if (m_limit <= m_cursor)
7983 goto basic_json_parser_33;
7987 goto basic_json_parser_60;
7989 goto basic_json_parser_33;
7995 goto basic_json_parser_60;
7999 goto basic_json_parser_33;
8003 goto basic_json_parser_60;
8005 goto basic_json_parser_33;
8007 basic_json_parser_55:
8011 goto basic_json_parser_61;
8013 goto basic_json_parser_33;
8014 basic_json_parser_56:
8017 return token_type::literal_null;
8019 basic_json_parser_58:
8022 return token_type::literal_true;
8024 basic_json_parser_60:
8026 if (m_limit <= m_cursor)
8035 goto basic_json_parser_33;
8039 goto basic_json_parser_63;
8041 goto basic_json_parser_33;
8047 goto basic_json_parser_63;
8051 goto basic_json_parser_33;
8055 goto basic_json_parser_63;
8057 goto basic_json_parser_33;
8059 basic_json_parser_61:
8062 return token_type::literal_false;
8064 basic_json_parser_63:
8066 if (m_limit <= m_cursor)
8075 goto basic_json_parser_33;
8079 goto basic_json_parser_31;
8081 goto basic_json_parser_33;
8087 goto basic_json_parser_31;
8091 goto basic_json_parser_33;
8095 goto basic_json_parser_31;
8097 goto basic_json_parser_33;
8104 void yyfill() noexcept
8106 if (m_stream ==
nullptr or not * m_stream)
8111 const auto offset_start = m_start - m_content;
8112 const auto offset_marker = m_marker - m_start;
8113 const auto offset_cursor = m_cursor - m_start;
8115 m_buffer.erase(0, static_cast<size_t>(offset_start));
8117 assert(m_stream !=
nullptr);
8118 std::getline(*m_stream, line);
8119 m_buffer +=
"\n" + line;
8121 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
8122 assert(m_content !=
nullptr);
8123 m_start = m_content;
8124 m_marker = m_start + offset_marker;
8125 m_cursor = m_start + offset_cursor;
8126 m_limit = m_start + m_buffer.size() - 1;
8132 assert(m_start !=
nullptr);
8133 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8134 static_cast<size_t>(m_cursor - m_start));
8162 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8165 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8221 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8222 4).c_str(),
nullptr, 16);
8225 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8228 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
8230 throw std::invalid_argument(
"missing low surrogate");
8234 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8235 (i + 7), 4).c_str(),
nullptr, 16);
8236 result += to_unicode(codepoint, codepoint2);
8243 result += to_unicode(codepoint);
8255 result.append(1, static_cast<typename string_t::value_type>(*i));
8282 long double str_to_float_t(
long double* ,
char** endptr)
const 8284 return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8302 double str_to_float_t(
double* ,
char** endptr)
const 8304 return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8322 float str_to_float_t(
float* ,
char** endptr)
const 8324 return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8348 void get_number(basic_json& result)
const 8350 assert(m_start !=
nullptr);
8352 const lexer::lexer_char_t* curptr = m_start;
8366 type = value_t::number_integer;
8367 max =
static_cast<uint64_t
>((std::numeric_limits<number_integer_t>::max)()) + 1;
8372 type = value_t::number_unsigned;
8373 max =
static_cast<uint64_t
>((std::numeric_limits<number_unsigned_t>::max)());
8377 for (; curptr < m_cursor; curptr++)
8380 if (*curptr < '0' || *curptr >
'9')
8385 type = value_t::number_float;
8390 type = value_t::number_float;
8395 if (type != value_t::number_float)
8398 auto temp = value * 10 + *curptr - 0x30;
8401 if (temp < value || temp > max)
8404 type = value_t::number_float;
8415 if (type == value_t::number_unsigned)
8417 result.m_value.number_unsigned = value;
8419 else if (type == value_t::number_integer)
8426 result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(
nullptr), NULL);
8430 result.m_type = type;
8435 std::istream* m_stream =
nullptr;
8439 const lexer_char_t* m_content =
nullptr;
8441 const lexer_char_t* m_start =
nullptr;
8443 const lexer_char_t* m_marker =
nullptr;
8445 const lexer_char_t* m_cursor =
nullptr;
8447 const lexer_char_t* m_limit =
nullptr;
8460 : callback(cb), m_lexer(s)
8468 : callback(cb), m_lexer(&_is)
8477 basic_json result = parse_internal(
true);
8479 expect(lexer::token_type::end_of_input);
8488 basic_json parse_internal(
bool keep)
8490 auto result = basic_json(value_t::discarded);
8494 case lexer::token_type::begin_object:
8496 if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
8499 result.m_type = value_t::object;
8500 result.m_value = json_value(value_t::object);
8507 if (last_token == lexer::token_type::end_object)
8510 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8512 result = basic_json(value_t::discarded);
8518 unexpect(lexer::token_type::value_separator);
8524 if (last_token == lexer::token_type::value_separator)
8530 expect(lexer::token_type::value_string);
8531 const auto key = m_lexer.get_string();
8533 bool keep_tag =
false;
8539 keep_tag = callback(depth, parse_event_t::key, k);
8549 expect(lexer::token_type::name_separator);
8553 auto value = parse_internal(keep);
8554 if (keep and keep_tag and not value.is_discarded())
8556 result[key] = std::move(value);
8559 while (last_token == lexer::token_type::value_separator);
8562 expect(lexer::token_type::end_object);
8564 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8566 result = basic_json(value_t::discarded);
8572 case lexer::token_type::begin_array:
8574 if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
8577 result.m_type = value_t::array;
8578 result.m_value = json_value(value_t::array);
8585 if (last_token == lexer::token_type::end_array)
8588 if (callback and not callback(--depth, parse_event_t::array_end, result))
8590 result = basic_json(value_t::discarded);
8596 unexpect(lexer::token_type::value_separator);
8602 if (last_token == lexer::token_type::value_separator)
8608 auto value = parse_internal(keep);
8609 if (keep and not value.is_discarded())
8611 result.push_back(std::move(value));
8614 while (last_token == lexer::token_type::value_separator);
8617 expect(lexer::token_type::end_array);
8619 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8621 result = basic_json(value_t::discarded);
8627 case lexer::token_type::literal_null:
8630 result.m_type = value_t::null;
8634 case lexer::token_type::value_string:
8636 const auto s = m_lexer.get_string();
8638 result = basic_json(s);
8642 case lexer::token_type::literal_true:
8645 result.m_type = value_t::boolean;
8646 result.m_value =
true;
8650 case lexer::token_type::literal_false:
8653 result.m_type = value_t::boolean;
8654 result.m_value =
false;
8658 case lexer::token_type::value_number:
8660 m_lexer.get_number(result);
8668 unexpect(last_token);
8672 if (keep and callback and not callback(depth, parse_event_t::value, result))
8674 result = basic_json(value_t::discarded);
8680 typename lexer::token_type get_token() noexcept
8682 last_token = m_lexer.scan();
8686 void expect(
typename lexer::token_type t)
const 8688 if (t != last_token)
8690 std::string error_msg =
"parse error - unexpected ";
8691 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token() +
"'") :
8692 lexer::token_type_name(last_token));
8693 error_msg +=
"; expected " + lexer::token_type_name(t);
8694 throw std::invalid_argument(error_msg);
8698 void unexpect(
typename lexer::token_type t)
const 8700 if (t == last_token)
8702 std::string error_msg =
"parse error - unexpected ";
8703 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token() +
"'") :
8704 lexer::token_type_name(last_token));
8705 throw std::invalid_argument(error_msg);
8715 typename lexer::token_type last_token = lexer::token_type::uninitialized;
8735 friend class basic_json;
8761 : reference_tokens(split(s))
8779 std::string to_string()
const noexcept
8783 for (
const auto& reference_token : reference_tokens)
8785 result +=
"/" + escape(reference_token);
8792 operator std::string()
const 8799 std::string pop_back()
8803 throw std::domain_error(
"JSON pointer has no parent");
8806 auto last = reference_tokens.back();
8807 reference_tokens.pop_back();
8812 bool is_root()
const 8814 return reference_tokens.empty();
8821 throw std::domain_error(
"JSON pointer has no parent");
8825 result.reference_tokens = {reference_tokens[0]};
8838 for (
const auto& reference_token : reference_tokens)
8840 switch (result->m_type)
8844 if (reference_token ==
"0")
8847 result = &result->operator[](0);
8852 result = &result->operator[](reference_token);
8857 case value_t::object:
8860 result = &result->operator[](reference_token);
8864 case value_t::array:
8867 result = &result->operator[](
static_cast<size_type>(std::stoi(reference_token)));
8880 throw std::domain_error(
"invalid value to unflatten");
8903 for (
const auto& reference_token : reference_tokens)
8905 switch (ptr->m_type)
8907 case value_t::object:
8910 ptr = &ptr->operator[](reference_token);
8914 case value_t::array:
8917 if (reference_token.size() > 1 and reference_token[0] ==
'0')
8919 throw std::domain_error(
"array index must not begin with '0'");
8922 if (reference_token ==
"-")
8925 ptr = &ptr->operator[](ptr->m_value.array->size());
8930 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
8937 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
8947 for (
const auto& reference_token : reference_tokens)
8949 switch (ptr->m_type)
8951 case value_t::object:
8954 ptr = &ptr->
at(reference_token);
8958 case value_t::array:
8960 if (reference_token ==
"-")
8963 throw std::out_of_range(
"array index '-' (" +
8964 std::to_string(ptr->m_value.array->size()) +
8965 ") is out of range");
8969 if (reference_token.size() > 1 and reference_token[0] ==
'0')
8971 throw std::domain_error(
"array index must not begin with '0'");
8975 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
8981 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
8999 for (
const auto& reference_token : reference_tokens)
9001 switch (ptr->m_type)
9003 case value_t::object:
9006 ptr = &ptr->operator[](reference_token);
9010 case value_t::array:
9012 if (reference_token ==
"-")
9015 throw std::out_of_range(
"array index '-' (" +
9016 std::to_string(ptr->m_value.array->size()) +
9017 ") is out of range");
9021 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9023 throw std::domain_error(
"array index must not begin with '0'");
9027 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9033 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9043 for (
const auto& reference_token : reference_tokens)
9045 switch (ptr->m_type)
9047 case value_t::object:
9050 ptr = &ptr->
at(reference_token);
9054 case value_t::array:
9056 if (reference_token ==
"-")
9059 throw std::out_of_range(
"array index '-' (" +
9060 std::to_string(ptr->m_value.array->size()) +
9061 ") is out of range");
9065 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9067 throw std::domain_error(
"array index must not begin with '0'");
9071 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9077 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9086 static std::vector<std::string> split(std::string reference_string)
9088 std::vector<std::string> result;
9091 if (reference_string.empty())
9097 if (reference_string[0] !=
'/')
9099 throw std::domain_error(
"JSON pointer must be empty or begin with '/'");
9107 size_t slash = reference_string.find_first_of(
"/", 1),
9116 slash = reference_string.find_first_of(
"/", start))
9120 auto reference_token = reference_string.substr(start, slash - start);
9123 for (
size_t pos = reference_token.find_first_of(
"~");
9124 pos != std::string::npos;
9125 pos = reference_token.find_first_of(
"~", pos + 1))
9127 assert(reference_token[pos] ==
'~');
9130 if (pos == reference_token.size() - 1 or
9131 (reference_token[pos + 1] !=
'0' and
9132 reference_token[pos + 1] !=
'1'))
9134 throw std::domain_error(
"escape error: '~' must be followed with '0' or '1'");
9139 unescape(reference_token);
9140 result.push_back(reference_token);
9161 static void replace_substring(std::string& s,
9162 const std::string& f,
9163 const std::string& t)
9165 assert(not f.empty());
9168 size_t pos = s.find(f);
9169 pos != std::string::npos;
9170 s.replace(pos, f.size(), t),
9171 pos = s.find(f, pos + t.size())
9176 static std::string escape(std::string s)
9179 replace_substring(s,
"~",
"~0");
9180 replace_substring(s,
"/",
"~1");
9185 static void unescape(std::string& s)
9188 replace_substring(s,
"~1",
"/");
9190 replace_substring(s,
"~0",
"~");
9200 static void flatten(
const std::string& reference_string,
9201 const basic_json& value,
9204 switch (value.m_type)
9206 case value_t::array:
9208 if (value.m_value.array->empty())
9211 result[reference_string] =
nullptr;
9216 for (
size_t i = 0; i < value.m_value.array->size(); ++i)
9218 flatten(reference_string +
"/" + std::to_string(i),
9219 value.m_value.array->operator[](i), result);
9225 case value_t::object:
9227 if (value.m_value.object->empty())
9230 result[reference_string] =
nullptr;
9235 for (
const auto& element : *value.m_value.object)
9237 flatten(reference_string +
"/" + escape(element.first),
9238 element.second, result);
9247 result[reference_string] = value;
9258 static basic_json unflatten(
const basic_json& value)
9262 throw std::domain_error(
"only objects can be unflattened");
9268 for (
const auto& element : *value.m_value.object)
9270 if (not element.second.is_primitive())
9272 throw std::domain_error(
"values in object must be primitive");
9280 json_pointer(element.first).get_and_create(result) = element.second;
9288 std::vector<std::string> reference_tokens {};
9333 return ptr.get_unchecked(
this);
9360 return ptr.get_unchecked(
this);
9385 return ptr.get_checked(
this);
9410 return ptr.get_checked(
this);
9435 basic_json flatten()
const 9437 basic_json result(value_t::object);
9438 json_pointer::flatten(
"", *
this, result);
9469 basic_json unflatten()
const 9471 return json_pointer::unflatten(*
this);
9519 basic_json patch(
const basic_json& json_patch)
const 9522 basic_json result = *
this;
9525 enum class patch_operations {add,
remove, replace, move, copy, test, invalid};
9527 const auto get_op = [](
const std::string op)
9531 return patch_operations::add;
9535 return patch_operations::remove;
9537 if (op ==
"replace")
9539 return patch_operations::replace;
9543 return patch_operations::move;
9547 return patch_operations::copy;
9551 return patch_operations::test;
9554 return patch_operations::invalid;
9558 const auto operation_add = [&result](
json_pointer & ptr, basic_json val)
9569 if (top_pointer != ptr)
9571 basic_json& x = result.
at(top_pointer);
9575 const auto last_path = ptr.pop_back();
9576 basic_json& parent = result[ptr];
9578 switch (parent.m_type)
9581 case value_t::object:
9584 parent[last_path] = val;
9588 case value_t::array:
9590 if (last_path ==
"-")
9597 const auto idx = std::stoi(last_path);
9598 if (static_cast<size_type>(idx) > parent.
size())
9601 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
9622 const auto operation_remove = [&result](
json_pointer & ptr)
9625 const auto last_path = ptr.pop_back();
9626 basic_json& parent = result.
at(ptr);
9632 auto it = parent.
find(last_path);
9633 if (it != parent.
end())
9639 throw std::out_of_range(
"key '" + last_path +
"' not found");
9645 parent.
erase(static_cast<size_type>(std::stoi(last_path)));
9653 throw std::invalid_argument(
"JSON patch must be an array of objects");
9657 for (
const auto& val : json_patch)
9660 const auto get_value = [&val](
const std::string & op,
9661 const std::string & member,
9662 bool string_type) -> basic_json&
9665 auto it = val.m_value.object->find(member);
9668 const auto error_msg = (op ==
"op") ?
"operation" :
"operation '" + op +
"'";
9671 if (it == val.m_value.object->end())
9673 throw std::invalid_argument(error_msg +
" must have member '" + member +
"'");
9677 if (string_type and not it->second.is_string())
9679 throw std::invalid_argument(error_msg +
" must have string member '" + member +
"'");
9687 if (not val.is_object())
9689 throw std::invalid_argument(
"JSON patch must be an array of objects");
9693 const std::string op = get_value(
"op",
"op",
true);
9694 const std::string path = get_value(op,
"path",
true);
9699 case patch_operations::add:
9701 operation_add(ptr, get_value(
"add",
"value",
false));
9705 case patch_operations::remove:
9707 operation_remove(ptr);
9711 case patch_operations::replace:
9714 result.
at(ptr) = get_value(
"replace",
"value",
false);
9718 case patch_operations::move:
9720 const std::string from_path = get_value(
"move",
"from",
true);
9724 basic_json v = result.
at(from_ptr);
9730 operation_remove(from_ptr);
9731 operation_add(ptr, v);
9735 case patch_operations::copy:
9737 const std::string from_path = get_value(
"copy",
"from",
true);;
9741 result[ptr] = result.
at(from_ptr);
9745 case patch_operations::test:
9747 bool success =
false;
9752 success = (result.
at(ptr) == get_value(
"test",
"value",
false));
9754 catch (std::out_of_range&)
9762 throw std::domain_error(
"unsuccessful: " + val.dump());
9768 case patch_operations::invalid:
9772 throw std::invalid_argument(
"operation value '" + op +
"' is invalid");
9812 static basic_json diff(
const basic_json& source,
9813 const basic_json& target,
9814 std::string path =
"")
9817 basic_json result(value_t::array);
9820 if (source == target)
9825 if (source.
type() != target.
type())
9837 switch (source.
type())
9839 case value_t::array:
9843 while (i < source.
size() and i < target.
size())
9846 auto temp_diff = diff(source[i], target[i], path +
"/" + std::to_string(i));
9847 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
9856 while (i < source.
size())
9860 result.insert(result.begin() + end_index, object(
9863 {
"path", path +
"/" + std::to_string(i)}
9869 while (i < target.
size())
9874 {
"path", path +
"/" + std::to_string(i)},
9875 {
"value", target[i]}
9883 case value_t::object:
9886 for (
auto it = source.
begin(); it != source.
end(); ++it)
9889 const auto key = json_pointer::escape(it.key());
9891 if (target.
find(it.key()) != target.
end())
9894 auto temp_diff = diff(it.value(), target[it.key()], path +
"/" + key);
9895 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
9900 result.push_back(
object(
9903 {
"path", path +
"/" + key}
9909 for (
auto it = target.
begin(); it != target.
end(); ++it)
9911 if (source.
find(it.key()) == source.
end())
9914 const auto key = json_pointer::escape(it.key());
9918 {
"path", path +
"/" + key},
9919 {
"value", it.value()}
9979 is_nothrow_move_constructible<nlohmann::json>::value and
9980 is_nothrow_move_assignable<nlohmann::json>::value
9998 const auto& h = hash<nlohmann::json::string_t>();
10016 inline nlohmann::json operator "" _json(
const char* s, std::size_t)
10032 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 10033 #pragma GCC diagnostic pop const_iterator(pointer object) noexcept
constructor for a given JSON instance
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
basic_json(const value_t value_type)
create an empty value with a given type
basic_json(const array_t &val)
create an array (explicit)
size_type count(typename object_t::key_type key) const
returns the number of occurrences of a key in a JSON object
const_reference operator[](size_type idx) const
access specified array element
reference value() const
return the value of an iterator
json_reverse_iterator & operator--()
pre-decrement (–it)
void clear() noexcept
clears the contents
bool operator==(const const_iterator &other) const
comparison: equal
json_reverse_iterator operator--(int)
post-decrement (it–)
reference operator[](T *(&key)[n])
access specified object element
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
iterator & operator+=(difference_type i)
add to iterator
static basic_json object(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an object from an initializer list
const_iterator operator-(difference_type i)
subtract from iterator
BooleanType boolean_t
a type for a boolean
const_iterator cbegin() const noexcept
returns a const iterator to the first element
reference operator+=(const typename object_t::value_type &val)
add an object to an object
reference operator*() const
return a reference to the value pointed to by the iterator
basic_json(const typename string_t::value_type *val)
create a string (explicit)
reference operator[](difference_type n) const
access to successor
iterator find(typename object_t::key_type key)
find an element in a JSON object
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
basic_json(const string_t &val)
create a string (explicit)
void push_back(const basic_json &val)
add an object to an array
void erase(const size_type idx)
remove element from a JSON array given an index
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
reference front()
access the first element
void swap(object_t &other)
exchanges the values
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
const_iterator & operator+=(difference_type i)
add to iterator
a class to store JSON values
basic_json(const int val) noexcept
create an integer number from an enum type (explicit)
reference value() const
return the value of an iterator
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
NumberIntegerType number_integer_t
a type for a number (integer)
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
const_iterator operator+(difference_type i)
add to iterator
constexpr bool is_object() const noexcept
return whether value is an object
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
a mutable random access iterator for the basic_json class
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
const_iterator operator++(int)
post-increment (it++)
const_iterator cend() const noexcept
returns a const iterator to one past the last element
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
basic_json(const number_integer_t val) noexcept
create an integer number (explicit)
static basic_json array(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an array from an initializer list
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
reference & operator=(basic_json other) noexcept( std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value )
copy assignment
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
PointerType get_ptr() noexcept
get a pointer value (implicit)
constexpr bool is_string() const noexcept
return whether value is a string
reference back()
access the last element
const value_type & const_reference
the type of an element const reference
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
void push_back(const typename object_t::value_type &val)
add an object to an object
void push_back(std::initializer_list< basic_json > init)
add an object to an object
json_pointer(const std::string &s="")
create JSON pointer
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
basic_json(std::nullptr_t) noexcept
create a null object (explicitly)
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
reference operator[](difference_type n) const
access to successor
static allocator_type get_allocator()
returns the allocator associated with the container
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
const_reference operator[](T *key) const
read-only access specified object element
json_reverse_iterator operator+(difference_type i) const
add to iterator
bool empty() const noexcept
checks whether the container is empty
std::size_t size_type
a type to represent container sizes
object_t::key_type key() const
return the key of an object iterator
const_iterator(const iterator &other) noexcept
copy constructor given a nonconst iterator
basic_json(const CompatibleArrayType &val)
create an array (implicit)
constexpr bool is_boolean() const noexcept
return whether value is a boolean
const_reference at(size_type idx) const
access specified array element with bounds checking
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
iterator insert(const_iterator pos, const basic_json &val)
inserts element
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
iterator & operator++()
pre-increment (++it)
bool operator<(const const_iterator &other) const
comparison: smaller
iterator operator++(int)
post-increment (it++)
basic_json(basic_json &&other) noexcept
move constructor
const_iterator operator--(int)
post-decrement (it–)
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
iterator & operator=(iterator other) noexcept( std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value )
copy assignment
object (unordered set of name/value pairs)
size_type max_size() const noexcept
returns the maximum possible number of elements
iterator operator--(int)
post-decrement (it–)
iterator operator-(difference_type i)
subtract from iterator
const_iterator & operator--()
pre-decrement (–it)
string_t dump(const int indent=-1) const
serialization
basic_json value_type
the type of elements in a basic_json container
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
AllocatorType< basic_json > allocator_type
the allocator type
StringType string_t
a type for a string
reference operator+=(const basic_json &val)
add an object to an array
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
difference_type operator-(const const_iterator &other) const
return difference
value_type & reference
the type of an element reference
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
constexpr bool is_discarded() const noexcept
return whether value is discarded
const_iterator begin() const noexcept
returns a const iterator to the first element
difference_type operator-(const iterator &other) const
return difference
constexpr bool is_array() const noexcept
return whether value is an array
iterator(const iterator &other) noexcept
copy constructor
namespace for Niels Lohmann
typename basic_json::difference_type difference_type
a type to represent differences between iterators
void swap(string_t &other)
exchanges the values
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
const_reference front() const
access the first element
bool operator>(const const_iterator &other) const
comparison: greater than
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
pointer operator->() const
dereference the iterator
NumberFloatType number_float_t
a type for a number (floating-point)
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
void swap(reference other) noexcept( std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value )
exchanges the values
value_t
the JSON type enumeration
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
constexpr bool is_null() const noexcept
return whether value is null
std::ptrdiff_t difference_type
a type to represent differences between iterators
ValueType get() const
get a value (explicit)
void swap(array_t &other)
exchanges the values
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
typename Base::reference reference
the reference type for the pointed-to element
const_reference back() const
access the last element
void push_back(basic_json &&val)
add an object to an array
array (ordered collection of values)
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
json_reverse_iterator & operator++()
pre-increment (++it)
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
string_t value(const typename object_t::key_type &key, const char *default_value) const
overload for a default value of type const char*
ReferenceType get_ref() const
get a reference value (implicit)
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
reference operator*() const
return a reference to the value pointed to by the iterator
friend bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
basic_json(const number_float_t val) noexcept
create a floating-point number (explicit)
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
iterator operator+(difference_type i)
add to iterator
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
bool operator<=(const const_iterator &other) const
comparison: less than or equal
InteratorType erase(InteratorType pos)
remove element given an iterator
basic_json(std::initializer_list< basic_json > init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
iterator(pointer object) noexcept
constructor for a given JSON instance
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
constexpr bool is_primitive() const noexcept
return whether type is primitive
const_iterator & operator++()
pre-increment (++it)
pointer operator->() const
dereference the iterator
reference value() const
return the value of an iterator
constexpr bool is_structured() const noexcept
return whether type is structured
std::bidirectional_iterator_tag iterator_category
the category of the iterator
basic_json(boolean_t val) noexcept
create a boolean (explicit)
iterator end() noexcept
returns an iterator to one past the last element
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
difference_type operator-(const json_reverse_iterator &other) const
return difference
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
iterator begin() noexcept
returns an iterator to the first element
basic_json(const CompatibleObjectType &val)
create an object (implicit)
const_iterator end() const noexcept
returns a const iterator to one past the last element
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
const_iterator & operator=(const_iterator other) noexcept( std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value )
copy assignment
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
reference operator[](const typename object_t::key_type &key)
access specified object element
object_t::key_type key() const
return the key of an object iterator
reference operator+=(basic_json &&val)
add an object to an array
reference operator[](difference_type n) const
access to successor
a const random access iterator for the basic_json class
constexpr bool is_number() const noexcept
return whether value is a number
a template for a reverse iterator class
basic_json(std::istream &i, parser_callback_t cb=nullptr)
construct a JSON value given an input stream
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
json_reverse_iterator operator++(int)
post-increment (it++)
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
reference operator[](size_type idx)
access specified array element
bool operator!=(const const_iterator &other) const
comparison: not equal
json_reverse_iterator & operator+=(difference_type i)
add to iterator
reference at(size_type idx)
access specified array element with bounds checking
size_type size() const noexcept
returns the number of elements
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
iterator & operator-=(difference_type i)
subtract from iterator
basic_json(const object_t &val)
create an object (explicit)
basic_json(const number_unsigned_t val) noexcept
create an unsigned integer number (explicit)
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
const_iterator(const const_iterator &other) noexcept
copy constructor
iterator & operator--()
pre-decrement (–it)
iterator insert(const_iterator pos, basic_json &&val)
inserts element
ReferenceType get_ref()
get a reference value (implicit)
const_iterator & operator-=(difference_type i)
subtract from iterator
basic_json(const CompatibleStringType &val)
create a string (implicit)
basic_json(const basic_json &other)
copy constructor
reference operator[](T *key)
access specified object element
parse_event_t
JSON callback events.