11 #ifndef NLOHMANN_JSON_HPP 12 #define NLOHMANN_JSON_HPP 23 #include <initializer_list> 33 #include <type_traits> 38 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 39 #pragma GCC diagnostic push 40 #pragma GCC diagnostic ignored "-Wfloat-equal" 63 struct has_mapped_type
66 template<
typename C>
static char test(
typename C::mapped_type*);
67 template<
typename C>
static char (&test(...))[2];
69 static constexpr
bool value =
sizeof(test<T>(0)) == 1;
146 template<
typename U,
typename V,
typename... Args>
class ObjectType = std::map,
147 template<
typename U,
typename... Args>
class ArrayType = std::vector,
148 class StringType = std::string,
149 class BooleanType = bool,
150 class NumberIntegerType = int64_t,
151 class NumberUnsignedType = uint64_t,
152 class NumberFloatType = double,
153 template<
typename U>
class AllocatorType = std::allocator
194 using pointer =
typename std::allocator_traits<allocator_type>::pointer;
196 using const_pointer =
typename std::allocator_traits<allocator_type>::const_pointer;
311 using object_t = ObjectType<StringType,
313 std::less<StringType>,
314 AllocatorType<std::pair<
const StringType,
361 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
680 template<
typename T,
typename... Args>
681 static T* create(Args&& ... args)
683 AllocatorType<T> alloc;
684 auto deleter = [&](T * object)
686 alloc.deallocate(
object, 1);
688 std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
689 alloc.construct(
object.
get(), std::forward<Args>(args)...);
690 return object.release();
722 json_value() =
default;
724 json_value(
boolean_t v) noexcept : boolean(v) {}
736 case value_t::object:
738 object = create<object_t>();
744 array = create<array_t>();
748 case value_t::string:
750 string = create<string_t>(
"");
754 case value_t::boolean:
760 case value_t::number_integer:
766 case value_t::number_unsigned:
772 case value_t::number_float:
788 string = create<string_t>(value);
794 object = create<object_t>(value);
798 json_value(
const array_t& value)
800 array = create<array_t>(value);
883 using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
933 : m_type(value_type), m_value(value_type)
960 basic_json() =
default;
1008 : m_type(
value_t::object), m_value(val)
1037 template <
class CompatibleObjectType,
typename 1039 std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1040 std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value,
int>::type
1047 m_value.object = create<object_t>(begin(val), end(val));
1070 : m_type(
value_t::array), m_value(val)
1099 template <
class CompatibleArrayType,
typename 1101 not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1102 not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1103 not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1104 not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1105 not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1106 not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1107 std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value,
int>::type
1114 m_value.array = create<array_t>(begin(val), end(val));
1139 : m_type(
value_t::string), m_value(val)
1189 template <
class CompatibleStringType,
typename 1191 std::is_constructible<string_t, CompatibleStringType>::value,
int>::type
1212 : m_type(value_t::boolean), m_value(val)
1238 template<
typename T,
1239 typename std::enable_if<
1240 not (std::is_same<T, int>::value)
1241 and std::is_same<T, number_integer_t>::value
1245 : m_type(value_t::number_integer), m_value(val)
1274 : m_type(value_t::number_integer),
1275 m_value(static_cast<number_integer_t>(val))
1303 template<
typename CompatibleNumberIntegerType,
typename 1305 std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1306 std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1307 std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1308 CompatibleNumberIntegerType>::type
1311 : m_type(value_t::number_integer),
1312 m_value(static_cast<number_integer_t>(val))
1332 template<
typename T,
1333 typename std::enable_if<
1334 not (std::is_same<T, int>::value)
1335 and std::is_same<T, number_unsigned_t>::value
1339 : m_type(value_t::number_unsigned), m_value(val)
1362 template <
typename CompatibleNumberUnsignedType,
typename 1364 std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1365 std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1366 !std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1367 CompatibleNumberUnsignedType >::type
1370 : m_type(value_t::number_unsigned),
1371 m_value(static_cast<number_unsigned_t>(val))
1399 : m_type(value_t::number_float), m_value(val)
1402 if (not std::isfinite(val))
1404 m_type = value_t::null;
1405 m_value = json_value();
1439 template<
typename CompatibleNumberFloatType,
typename =
typename 1441 std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1442 std::is_floating_point<CompatibleNumberFloatType>::value>::type
1518 bool type_deduction =
true,
1519 value_t manual_type = value_t::array)
1522 bool is_an_object =
true;
1526 for (
const auto& element : init)
1528 if (not element.is_array() or element.size() != 2
1529 or not element[0].is_string())
1533 is_an_object =
false;
1539 if (not type_deduction)
1542 if (manual_type == value_t::array)
1544 is_an_object =
false;
1548 if (manual_type == value_t::object and not is_an_object)
1550 throw std::domain_error(
"cannot create object from initializer list");
1557 m_type = value_t::object;
1558 m_value = value_t::object;
1560 assert(m_value.object !=
nullptr);
1562 for (
auto& element : init)
1564 m_value.object->emplace(std::move(*(element[0].m_value.string)), std::move(element[1]));
1570 m_type = value_t::array;
1571 m_value.array = create<array_t>(std::move(init));
1609 static basic_json
array(std::initializer_list<basic_json> init =
1610 std::initializer_list<basic_json>())
1612 return basic_json(init,
false, value_t::array);
1649 static basic_json
object(std::initializer_list<basic_json> init =
1650 std::initializer_list<basic_json>())
1652 return basic_json(init,
false, value_t::object);
1676 m_value.array = create<array_t>(cnt, val);
1713 template <
class InputIT,
typename 1715 std::is_same<InputIT, typename basic_json_t::iterator>::value or
1716 std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1719 basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1722 if (first.m_object != last.m_object)
1724 throw std::domain_error(
"iterators are not compatible");
1730 case value_t::boolean:
1731 case value_t::number_float:
1732 case value_t::number_integer:
1733 case value_t::number_unsigned:
1734 case value_t::string:
1736 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1738 throw std::out_of_range(
"iterators out of range");
1751 case value_t::number_integer:
1753 assert(first.m_object !=
nullptr);
1754 m_value.number_integer = first.m_object->m_value.number_integer;
1758 case value_t::number_unsigned:
1760 assert(first.m_object !=
nullptr);
1761 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1765 case value_t::number_float:
1767 assert(first.m_object !=
nullptr);
1768 m_value.number_float = first.m_object->m_value.number_float;
1772 case value_t::boolean:
1774 assert(first.m_object !=
nullptr);
1775 m_value.boolean = first.m_object->m_value.boolean;
1779 case value_t::string:
1781 assert(first.m_object !=
nullptr);
1782 m_value = *first.m_object->m_value.string;
1786 case value_t::object:
1788 m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1792 case value_t::array:
1794 m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1800 assert(first.m_object !=
nullptr);
1801 throw std::domain_error(
"cannot use construct with iterators from " + first.m_object->type_name());
1828 *
this = parser(i, cb).parse();
1858 : m_type(other.m_type)
1862 case value_t::object:
1864 assert(other.m_value.object !=
nullptr);
1865 m_value = *other.m_value.object;
1869 case value_t::array:
1871 assert(other.m_value.array !=
nullptr);
1872 m_value = *other.m_value.array;
1876 case value_t::string:
1878 assert(other.m_value.string !=
nullptr);
1879 m_value = *other.m_value.string;
1883 case value_t::boolean:
1885 m_value = other.m_value.boolean;
1889 case value_t::number_integer:
1891 m_value = other.m_value.number_integer;
1895 case value_t::number_unsigned:
1897 m_value = other.m_value.number_unsigned;
1901 case value_t::number_float:
1903 m_value = other.m_value.number_float;
1933 : m_type(
std::move(other.m_type)),
1934 m_value(
std::move(other.m_value))
1937 other.m_type = value_t::null;
1965 std::is_nothrow_move_constructible<value_t>::value and
1966 std::is_nothrow_move_assignable<value_t>::value and
1967 std::is_nothrow_move_constructible<json_value>::value and
1968 std::is_nothrow_move_assignable<json_value>::value
1972 swap(m_type, other.m_type);
1973 swap(m_value, other.m_value);
1996 case value_t::object:
1998 AllocatorType<object_t> alloc;
1999 alloc.destroy(m_value.object);
2000 alloc.deallocate(m_value.object, 1);
2004 case value_t::array:
2006 AllocatorType<array_t> alloc;
2007 alloc.destroy(m_value.array);
2008 alloc.deallocate(m_value.array, 1);
2012 case value_t::string:
2014 AllocatorType<string_t> alloc;
2015 alloc.destroy(m_value.string);
2016 alloc.deallocate(m_value.string, 1);
2063 std::stringstream ss;
2067 dump(ss,
true, static_cast<unsigned int>(indent));
2127 return is_null() or is_string() or is_boolean() or is_number();
2154 return is_array() or is_object();
2176 return m_type == value_t::null;
2198 return m_type == value_t::boolean;
2228 return is_number_integer() or is_number_float();
2257 return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2285 return m_type == value_t::number_unsigned;
2313 return m_type == value_t::number_float;
2335 return m_type == value_t::object;
2357 return m_type == value_t::array;
2379 return m_type == value_t::string;
2406 return m_type == value_t::discarded;
2440 template <
class T,
typename 2442 std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2443 std::is_convertible<basic_json_t, typename T::mapped_type>::value
2445 T get_impl(T*)
const 2449 assert(m_value.object !=
nullptr);
2450 return T(m_value.object->begin(), m_value.object->end());
2454 throw std::domain_error(
"type must be object, but is " + type_name());
2463 assert(m_value.object !=
nullptr);
2464 return *(m_value.object);
2468 throw std::domain_error(
"type must be object, but is " + type_name());
2473 template <
class T,
typename 2475 std::is_convertible<basic_json_t, typename T::value_type>::value and
2476 not std::is_same<basic_json_t, typename T::value_type>::value and
2477 not std::is_arithmetic<T>::value and
2478 not std::is_convertible<std::string, T>::value and
2479 not has_mapped_type<T>::value
2481 T get_impl(T*)
const 2486 assert(m_value.array !=
nullptr);
2487 std::transform(m_value.array->begin(), m_value.array->end(),
2488 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2490 return i.
get<
typename T::value_type>();
2496 throw std::domain_error(
"type must be array, but is " + type_name());
2501 template <
class T,
typename 2503 std::is_convertible<basic_json_t, T>::value and
2504 not std::is_same<basic_json_t, T>::value
2506 std::vector<T> get_impl(std::vector<T>*)
const 2510 std::vector<T> to_vector;
2511 assert(m_value.array !=
nullptr);
2512 to_vector.reserve(m_value.array->size());
2513 std::transform(m_value.array->begin(), m_value.array->end(),
2514 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2522 throw std::domain_error(
"type must be array, but is " + type_name());
2527 template <
class T,
typename 2529 std::is_same<basic_json, typename T::value_type>::value and
2530 not has_mapped_type<T>::value
2532 T get_impl(T*)
const 2536 assert(m_value.array !=
nullptr);
2537 return T(m_value.array->begin(), m_value.array->end());
2541 throw std::domain_error(
"type must be array, but is " + type_name());
2550 assert(m_value.array !=
nullptr);
2551 return *(m_value.array);
2555 throw std::domain_error(
"type must be array, but is " + type_name());
2560 template <
typename T,
typename 2562 std::is_convertible<string_t, T>::value
2564 T get_impl(T*)
const 2568 assert(m_value.string !=
nullptr);
2569 return *m_value.string;
2573 throw std::domain_error(
"type must be string, but is " + type_name());
2578 template<
typename T,
typename 2580 std::is_arithmetic<T>::value
2582 T get_impl(T*)
const 2586 case value_t::number_integer:
2588 return static_cast<T
>(m_value.number_integer);
2591 case value_t::number_unsigned:
2593 return static_cast<T
>(m_value.number_unsigned);
2596 case value_t::number_float:
2598 return static_cast<T
>(m_value.number_float);
2603 throw std::domain_error(
"type must be number, but is " + type_name());
2613 :
throw std::domain_error(
"type must be boolean, but is " + type_name());
2619 return is_object() ? m_value.object :
nullptr;
2625 return is_object() ? m_value.object :
nullptr;
2631 return is_array() ? m_value.array :
nullptr;
2635 constexpr
const array_t* get_impl_ptr(
const array_t*)
const noexcept
2637 return is_array() ? m_value.array :
nullptr;
2643 return is_string() ? m_value.string :
nullptr;
2649 return is_string() ? m_value.string :
nullptr;
2655 return is_boolean() ? &m_value.boolean :
nullptr;
2661 return is_boolean() ? &m_value.boolean :
nullptr;
2667 return is_number_integer() ? &m_value.number_integer :
nullptr;
2673 return is_number_integer() ? &m_value.number_integer :
nullptr;
2679 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2685 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2691 return is_number_float() ? &m_value.number_float :
nullptr;
2697 return is_number_float() ? &m_value.number_float :
nullptr;
2711 template<
typename ReferenceType,
typename ThisType>
2712 static ReferenceType get_ref_impl(ThisType& obj)
2715 using PointerType =
typename std::add_pointer<ReferenceType>::type;
2716 auto ptr = obj.template get_ptr<PointerType>();
2724 throw std::domain_error(
"incompatible ReferenceType for get_ref, actual type is " +
2767 template<
typename ValueType,
typename 2769 not std::is_pointer<ValueType>::value
2771 ValueType
get()
const 2773 return get_impl(static_cast<ValueType*>(
nullptr));
2802 template<
typename PointerType,
typename 2804 std::is_pointer<PointerType>::value
2806 PointerType
get() noexcept
2809 return get_ptr<PointerType>();
2816 template<
typename PointerType,
typename 2818 std::is_pointer<PointerType>::value
2820 constexpr
const PointerType
get()
const noexcept
2823 return get_ptr<PointerType>();
2851 template<
typename PointerType,
typename 2853 std::is_pointer<PointerType>::value
2858 return get_impl_ptr(static_cast<PointerType>(
nullptr));
2865 template<
typename PointerType,
typename 2867 std::is_pointer<PointerType>::value
2868 and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2870 constexpr
const PointerType
get_ptr() const noexcept
2873 return get_impl_ptr(static_cast<const PointerType>(
nullptr));
2902 template<
typename ReferenceType,
typename 2904 std::is_reference<ReferenceType>::value
2909 return get_ref_impl<ReferenceType>(*this);
2916 template<
typename ReferenceType,
typename 2918 std::is_reference<ReferenceType>::value
2919 and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
2924 return get_ref_impl<ReferenceType>(*this);
2955 template <
typename ValueType,
typename 2957 not std::is_pointer<ValueType>::value
2958 and not std::is_same<ValueType, typename string_t::value_type>::value
2959 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015 2960 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
2963 operator ValueType()
const 2966 return get<ValueType>();
3008 assert(m_value.array !=
nullptr);
3009 return m_value.array->at(idx);
3011 catch (std::out_of_range&)
3014 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3019 throw std::domain_error(
"cannot use at() with " + type_name());
3052 assert(m_value.array !=
nullptr);
3053 return m_value.array->at(idx);
3055 catch (std::out_of_range&)
3058 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3063 throw std::domain_error(
"cannot use at() with " + type_name());
3100 assert(m_value.object !=
nullptr);
3101 return m_value.object->at(key);
3103 catch (std::out_of_range&)
3106 throw std::out_of_range(
"key '" + key +
"' not found");
3111 throw std::domain_error(
"cannot use at() with " + type_name());
3148 assert(m_value.object !=
nullptr);
3149 return m_value.object->at(key);
3151 catch (std::out_of_range&)
3154 throw std::out_of_range(
"key '" + key +
"' not found");
3159 throw std::domain_error(
"cannot use at() with " + type_name());
3193 m_type = value_t::array;
3194 m_value.
array = create<array_t>();
3201 assert(m_value.array !=
nullptr);
3202 for (
size_t i = m_value.array->size(); i <= idx; ++i)
3204 m_value.array->push_back(basic_json());
3207 return m_value.array->operator[](idx);
3211 throw std::domain_error(
"cannot use operator[] with " + type_name());
3239 assert(m_value.array !=
nullptr);
3240 return m_value.array->operator[](idx);
3244 throw std::domain_error(
"cannot use operator[] with " + type_name());
3280 m_type = value_t::object;
3281 m_value.
object = create<object_t>();
3287 assert(m_value.object !=
nullptr);
3288 return m_value.object->operator[](key);
3292 throw std::domain_error(
"cannot use operator[] with " + type_name());
3328 assert(m_value.object !=
nullptr);
3329 assert(m_value.object->find(key) != m_value.object->end());
3330 return m_value.object->find(key)->second;
3334 throw std::domain_error(
"cannot use operator[] with " + type_name());
3365 template<
typename T, std::
size_t n>
3368 return operator[](static_cast<const T>(key));
3400 template<
typename T, std::
size_t n>
3403 return operator[](static_cast<const T>(key));
3433 template<
typename T>
3439 m_type = value_t::object;
3440 m_value = value_t::object;
3446 assert(m_value.object !=
nullptr);
3447 return m_value.object->operator[](key);
3451 throw std::domain_error(
"cannot use operator[] with " + type_name());
3482 template<
typename T>
3488 assert(m_value.object !=
nullptr);
3489 assert(m_value.object->find(key) != m_value.object->end());
3490 return m_value.object->find(key)->second;
3494 throw std::domain_error(
"cannot use operator[] with " + type_name());
3546 template <
class ValueType,
typename 3548 std::is_convertible<basic_json_t, ValueType>::value
3550 ValueType
value(
const typename object_t::key_type& key, ValueType default_value)
const 3556 const auto it = find(key);
3563 return default_value;
3568 throw std::domain_error(
"cannot use value() with " + type_name());
3576 string_t value(
const typename object_t::key_type& key,
const char* default_value)
const 3578 return value(key,
string_t(default_value));
3709 template <
class InteratorType,
typename 3711 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3712 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3718 if (
this != pos.m_object)
3720 throw std::domain_error(
"iterator does not fit current value");
3723 InteratorType result = end();
3727 case value_t::boolean:
3728 case value_t::number_float:
3729 case value_t::number_integer:
3730 case value_t::number_unsigned:
3731 case value_t::string:
3733 if (not pos.m_it.primitive_iterator.is_begin())
3735 throw std::out_of_range(
"iterator out of range");
3740 delete m_value.string;
3741 m_value.string =
nullptr;
3744 m_type = value_t::null;
3748 case value_t::object:
3750 assert(m_value.object !=
nullptr);
3751 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3755 case value_t::array:
3757 assert(m_value.array !=
nullptr);
3758 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3764 throw std::domain_error(
"cannot use erase() with " + type_name());
3817 template <
class InteratorType,
typename 3819 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3820 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3823 InteratorType
erase(InteratorType first, InteratorType last)
3826 if (
this != first.m_object or
this != last.m_object)
3828 throw std::domain_error(
"iterators do not fit current value");
3831 InteratorType result = end();
3835 case value_t::boolean:
3836 case value_t::number_float:
3837 case value_t::number_integer:
3838 case value_t::number_unsigned:
3839 case value_t::string:
3841 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3843 throw std::out_of_range(
"iterators out of range");
3848 delete m_value.string;
3849 m_value.string =
nullptr;
3852 m_type = value_t::null;
3856 case value_t::object:
3858 assert(m_value.object !=
nullptr);
3859 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3860 last.m_it.object_iterator);
3864 case value_t::array:
3866 assert(m_value.array !=
nullptr);
3867 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3868 last.m_it.array_iterator);
3874 throw std::domain_error(
"cannot use erase() with " + type_name());
3915 assert(m_value.object !=
nullptr);
3916 return m_value.object->erase(key);
3920 throw std::domain_error(
"cannot use erase() with " + type_name());
3955 throw std::out_of_range(
"index out of range");
3958 assert(m_value.array !=
nullptr);
3959 m_value.array->erase(m_value.array->begin() +
static_cast<difference_type>(idx));
3963 throw std::domain_error(
"cannot use erase() with " + type_name());
3996 auto result = end();
4000 assert(m_value.object !=
nullptr);
4001 result.m_it.object_iterator = m_value.object->find(key);
4013 auto result = cend();
4017 assert(m_value.object !=
nullptr);
4018 result.m_it.object_iterator = m_value.object->find(key);
4045 assert(not is_object() or m_value.object !=
nullptr);
4046 return is_object() ? m_value.object->count(key) : 0;
4334 template<
typename IteratorType>
class iteration_proxy;
4350 return iteration_proxy<iterator>(cont);
4358 return iteration_proxy<const_iterator>(cont);
4414 case value_t::array:
4416 assert(m_value.array !=
nullptr);
4417 return m_value.array->empty();
4420 case value_t::object:
4422 assert(m_value.object !=
nullptr);
4423 return m_value.object->empty();
4477 case value_t::array:
4479 assert(m_value.array !=
nullptr);
4480 return m_value.array->size();
4483 case value_t::object:
4485 assert(m_value.object !=
nullptr);
4486 return m_value.object->size();
4537 case value_t::array:
4539 assert(m_value.array !=
nullptr);
4540 return m_value.array->max_size();
4543 case value_t::object:
4545 assert(m_value.object !=
nullptr);
4546 return m_value.object->max_size();
4596 case value_t::number_integer:
4598 m_value.number_integer = 0;
4602 case value_t::number_unsigned:
4604 m_value.number_unsigned = 0;
4608 case value_t::number_float:
4610 m_value.number_float = 0.0;
4614 case value_t::boolean:
4616 m_value.boolean =
false;
4620 case value_t::string:
4622 assert(m_value.string !=
nullptr);
4623 m_value.string->clear();
4627 case value_t::array:
4629 assert(m_value.array !=
nullptr);
4630 m_value.array->clear();
4634 case value_t::object:
4636 assert(m_value.object !=
nullptr);
4637 m_value.object->clear();
4671 if (not(is_null() or is_array()))
4673 throw std::domain_error(
"cannot use push_back() with " + type_name());
4679 m_type = value_t::array;
4680 m_value = value_t::array;
4684 assert(m_value.array !=
nullptr);
4685 m_value.array->push_back(std::move(val));
4687 val.m_type = value_t::null;
4696 push_back(std::move(val));
4707 if (not(is_null() or is_array()))
4709 throw std::domain_error(
"cannot use push_back() with " + type_name());
4715 m_type = value_t::array;
4716 m_value = value_t::array;
4720 assert(m_value.array !=
nullptr);
4721 m_value.array->push_back(val);
4757 if (not(is_null() or is_object()))
4759 throw std::domain_error(
"cannot use push_back() with " + type_name());
4765 m_type = value_t::object;
4766 m_value = value_t::object;
4770 assert(m_value.object !=
nullptr);
4771 m_value.object->insert(val);
4781 return operator[](val.first);
4812 if (pos.m_object !=
this)
4814 throw std::domain_error(
"iterator does not fit current value");
4819 assert(m_value.array !=
nullptr);
4820 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4825 throw std::domain_error(
"cannot use insert() with " + type_name());
4835 return insert(pos, val);
4868 if (pos.m_object !=
this)
4870 throw std::domain_error(
"iterator does not fit current value");
4875 assert(m_value.array !=
nullptr);
4876 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4881 throw std::domain_error(
"cannot use insert() with " + type_name());
4920 throw std::domain_error(
"cannot use insert() with " + type_name());
4924 if (pos.m_object !=
this)
4926 throw std::domain_error(
"iterator does not fit current value");
4929 if (first.m_object != last.m_object)
4931 throw std::domain_error(
"iterators do not fit");
4934 if (first.m_object ==
this or last.m_object ==
this)
4936 throw std::domain_error(
"passed iterators may not belong to container");
4941 assert(m_value.array !=
nullptr);
4942 result.m_it.array_iterator = m_value.array->insert(
4943 pos.m_it.array_iterator,
4944 first.m_it.array_iterator,
4945 last.m_it.array_iterator);
4978 throw std::domain_error(
"cannot use insert() with " + type_name());
4982 if (pos.m_object !=
this)
4984 throw std::domain_error(
"iterator does not fit current value");
4989 assert(m_value.array !=
nullptr);
4990 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5012 std::is_nothrow_move_constructible<value_t>::value and
5013 std::is_nothrow_move_assignable<value_t>::value and
5014 std::is_nothrow_move_constructible<json_value>::value and
5015 std::is_nothrow_move_assignable<json_value>::value
5018 std::swap(m_type, other.m_type);
5019 std::swap(m_value, other.m_value);
5047 assert(m_value.array !=
nullptr);
5048 std::swap(*(m_value.array), other);
5052 throw std::domain_error(
"cannot use swap() with " + type_name());
5081 assert(m_value.object !=
nullptr);
5082 std::swap(*(m_value.object), other);
5086 throw std::domain_error(
"cannot use swap() with " + type_name());
5115 assert(m_value.string !=
nullptr);
5116 std::swap(*(m_value.string), other);
5120 throw std::domain_error(
"cannot use swap() with " + type_name());
5146 static constexpr std::array<uint8_t, 8> order = {{
5159 if (lhs == value_t::discarded or rhs == value_t::discarded)
5164 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
5193 const auto lhs_type = lhs.type();
5194 const auto rhs_type = rhs.type();
5196 if (lhs_type == rhs_type)
5200 case value_t::array:
5202 assert(lhs.m_value.array !=
nullptr);
5203 assert(rhs.m_value.array !=
nullptr);
5204 return *lhs.m_value.array == *rhs.m_value.array;
5206 case value_t::object:
5208 assert(lhs.m_value.object !=
nullptr);
5209 assert(rhs.m_value.object !=
nullptr);
5210 return *lhs.m_value.object == *rhs.m_value.object;
5216 case value_t::string:
5218 assert(lhs.m_value.string !=
nullptr);
5219 assert(rhs.m_value.string !=
nullptr);
5220 return *lhs.m_value.string == *rhs.m_value.string;
5222 case value_t::boolean:
5224 return lhs.m_value.boolean == rhs.m_value.boolean;
5226 case value_t::number_integer:
5228 return lhs.m_value.number_integer == rhs.m_value.number_integer;
5230 case value_t::number_unsigned:
5232 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5234 case value_t::number_float:
5236 return lhs.m_value.number_float == rhs.m_value.number_float;
5244 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5246 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5248 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5250 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_integer);
5252 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5254 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5256 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5258 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5260 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5262 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5264 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5266 return lhs.m_value.number_integer ==
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5322 return not (lhs == rhs);
5354 return not v.is_null();
5383 const auto lhs_type = lhs.type();
5384 const auto rhs_type = rhs.type();
5386 if (lhs_type == rhs_type)
5390 case value_t::array:
5392 assert(lhs.m_value.array !=
nullptr);
5393 assert(rhs.m_value.array !=
nullptr);
5394 return *lhs.m_value.array < *rhs.m_value.array;
5396 case value_t::object:
5398 assert(lhs.m_value.object !=
nullptr);
5399 assert(rhs.m_value.object !=
nullptr);
5400 return *lhs.m_value.object < *rhs.m_value.object;
5406 case value_t::string:
5408 assert(lhs.m_value.string !=
nullptr);
5409 assert(rhs.m_value.string !=
nullptr);
5410 return *lhs.m_value.string < *rhs.m_value.string;
5412 case value_t::boolean:
5414 return lhs.m_value.boolean < rhs.m_value.boolean;
5416 case value_t::number_integer:
5418 return lhs.m_value.number_integer < rhs.m_value.number_integer;
5420 case value_t::number_unsigned:
5422 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5424 case value_t::number_float:
5426 return lhs.m_value.number_float < rhs.m_value.number_float;
5434 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5436 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5438 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5440 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_integer);
5442 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5444 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5446 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5448 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5450 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5452 return lhs.m_value.number_integer <
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5454 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5456 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5462 return operator<(lhs_type, rhs_type);
5484 return not (rhs < lhs);
5506 return not (lhs <= rhs);
5528 return not (lhs < rhs);
5563 friend std::ostream&
operator<<(std::ostream& o,
const basic_json& j)
5566 const bool pretty_print = (o.width() > 0);
5567 const auto indentation = (pretty_print ? o.width() : 0);
5573 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
5581 friend std::ostream&
operator>>(
const basic_json& j, std::ostream& o)
5622 return parser(s, cb).
parse();
5651 return parser(i, cb).
parse();
5659 return parser(i, cb).
parse();
5687 j = parser(i).
parse();
5697 j = parser(i).
parse();
5710 string_t type_name()
const noexcept
5716 case value_t::object:
5718 case value_t::array:
5720 case value_t::string:
5722 case value_t::boolean:
5724 case value_t::discarded:
5739 static std::size_t extra_space(
const string_t& s) noexcept
5741 std::size_t result = 0;
5743 for (
const auto& c : s)
5762 if (c >= 0x00 and c <= 0x1f)
5790 const auto space = extra_space(s);
5797 string_t result(s.size() + space,
'\\');
5798 std::size_t pos = 0;
5800 for (
const auto& c : s)
5807 result[pos + 1] =
'"';
5823 result[pos + 1] =
'b';
5831 result[pos + 1] =
'f';
5839 result[pos + 1] =
'n';
5847 result[pos + 1] =
'r';
5855 result[pos + 1] =
't';
5862 if (c >= 0x00 and c <= 0x1f)
5866 auto hexify = [](
const char v) ->
char 5868 return (v < 10) ? (
'0' + v) : (
'a' + v - 10);
5873 {
'u',
'0',
'0', hexify(c >> 4), hexify(c & 0x0f)
5911 void dump(std::ostream& o,
5912 const bool pretty_print,
5913 const unsigned int indent_step,
5914 const unsigned int current_indent = 0)
const 5917 unsigned int new_indent = current_indent;
5921 case value_t::object:
5923 assert(m_value.object !=
nullptr);
5925 if (m_value.object->empty())
5936 new_indent += indent_step;
5940 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5942 if (i != m_value.object->cbegin())
5944 o << (pretty_print ?
",\n" :
",");
5946 o <<
string_t(new_indent,
' ') <<
"\"" 5947 << escape_string(i->first) <<
"\":" 5948 << (pretty_print ?
" " :
"");
5949 i->second.dump(o, pretty_print, indent_step, new_indent);
5955 new_indent -= indent_step;
5959 o <<
string_t(new_indent,
' ') +
"}";
5963 case value_t::array:
5965 assert(m_value.array !=
nullptr);
5967 if (m_value.array->empty())
5978 new_indent += indent_step;
5982 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5984 if (i != m_value.array->cbegin())
5986 o << (pretty_print ?
",\n" :
",");
5989 i->dump(o, pretty_print, indent_step, new_indent);
5995 new_indent -= indent_step;
5999 o <<
string_t(new_indent,
' ') <<
"]";
6003 case value_t::string:
6005 assert(m_value.string !=
nullptr);
6006 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
6010 case value_t::boolean:
6012 o << (m_value.boolean ?
"true" :
"false");
6016 case value_t::number_integer:
6018 o << m_value.number_integer;
6022 case value_t::number_unsigned:
6024 o << m_value.number_unsigned;
6028 case value_t::number_float:
6036 if (std::fmod(m_value.number_float, 1) == 0)
6038 o << std::fixed << std::setprecision(1);
6043 o.unsetf(std::ios_base::floatfield);
6044 o << std::setprecision(std::numeric_limits<double>::digits10);
6046 o << m_value.number_float;
6050 case value_t::discarded:
6070 value_t m_type = value_t::null;
6073 json_value m_value = {};
6090 class primitive_iterator_t
6094 void set_begin() noexcept
6100 void set_end() noexcept
6106 constexpr
bool is_begin()
const noexcept
6108 return (m_it == begin_value);
6112 constexpr
bool is_end()
const noexcept
6114 return (m_it == end_value);
6134 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6144 struct internal_iterator
6147 typename object_t::iterator object_iterator;
6149 typename array_t::iterator array_iterator;
6151 primitive_iterator_t primitive_iterator;
6154 internal_iterator() noexcept
6155 : object_iterator(), array_iterator(), primitive_iterator()
6160 template<
typename IteratorType>
6161 class iteration_proxy
6165 class iteration_proxy_internal
6169 IteratorType anchor;
6171 size_t array_index = 0;
6174 explicit iteration_proxy_internal(IteratorType it) noexcept
6179 iteration_proxy_internal& operator*()
6185 iteration_proxy_internal& operator++()
6194 bool operator!= (
const iteration_proxy_internal& o)
const 6196 return anchor != o.anchor;
6202 assert(anchor.m_object !=
nullptr);
6204 switch (anchor.m_object->type())
6207 case value_t::array:
6209 return std::to_string(array_index);
6213 case value_t::object:
6215 return anchor.key();
6227 typename IteratorType::reference value()
const 6229 return anchor.value();
6234 typename IteratorType::reference container;
6238 explicit iteration_proxy(
typename IteratorType::reference cont)
6243 iteration_proxy_internal begin() noexcept
6245 return iteration_proxy_internal(container.begin());
6249 iteration_proxy_internal end() noexcept
6251 return iteration_proxy_internal(container.end());
6269 class const_iterator :
public std::iterator<std::random_access_iterator_tag, const basic_json>
6272 friend class basic_json;
6293 assert(m_object !=
nullptr);
6295 switch (m_object->m_type)
6299 m_it.object_iterator =
typename object_t::iterator();
6305 m_it.array_iterator =
typename array_t::iterator();
6311 m_it.primitive_iterator = primitive_iterator_t();
6319 : m_object(other.m_object)
6321 assert(m_object !=
nullptr);
6323 switch (m_object->m_type)
6327 m_it.object_iterator = other.m_it.object_iterator;
6333 m_it.array_iterator = other.m_it.array_iterator;
6339 m_it.primitive_iterator = other.m_it.primitive_iterator;
6347 : m_object(other.m_object), m_it(other.m_it)
6352 std::is_nothrow_move_constructible<pointer>::value and
6353 std::is_nothrow_move_assignable<pointer>::value and
6354 std::is_nothrow_move_constructible<internal_iterator>::value and
6355 std::is_nothrow_move_assignable<internal_iterator>::value
6358 std::swap(m_object, other.m_object);
6359 std::swap(m_it, other.m_it);
6365 void set_begin() noexcept
6367 assert(m_object !=
nullptr);
6369 switch (m_object->m_type)
6373 assert(m_object->m_value.object !=
nullptr);
6374 m_it.object_iterator = m_object->m_value.object->begin();
6380 assert(m_object->m_value.array !=
nullptr);
6381 m_it.array_iterator = m_object->m_value.array->begin();
6388 m_it.primitive_iterator.set_end();
6394 m_it.primitive_iterator.set_begin();
6401 void set_end() noexcept
6403 assert(m_object !=
nullptr);
6405 switch (m_object->m_type)
6409 assert(m_object->m_value.object !=
nullptr);
6410 m_it.object_iterator = m_object->m_value.object->end();
6416 assert(m_object->m_value.array !=
nullptr);
6417 m_it.array_iterator = m_object->m_value.array->end();
6423 m_it.primitive_iterator.set_end();
6433 assert(m_object !=
nullptr);
6435 switch (m_object->m_type)
6439 assert(m_object->m_value.object);
6440 assert(m_it.object_iterator != m_object->m_value.object->end());
6441 return m_it.object_iterator->second;
6446 assert(m_object->m_value.array);
6447 assert(m_it.array_iterator != m_object->m_value.array->end());
6448 return *m_it.array_iterator;
6453 throw std::out_of_range(
"cannot get value");
6458 if (m_it.primitive_iterator.is_begin())
6464 throw std::out_of_range(
"cannot get value");
6473 assert(m_object !=
nullptr);
6475 switch (m_object->m_type)
6479 assert(m_object->m_value.object);
6480 assert(m_it.object_iterator != m_object->m_value.object->end());
6481 return &(m_it.object_iterator->second);
6486 assert(m_object->m_value.array);
6487 assert(m_it.array_iterator != m_object->m_value.array->end());
6488 return &*m_it.array_iterator;
6493 if (m_it.primitive_iterator.is_begin())
6499 throw std::out_of_range(
"cannot get value");
6508 auto result = *
this;
6516 assert(m_object !=
nullptr);
6518 switch (m_object->m_type)
6522 ++m_it.object_iterator;
6528 ++m_it.array_iterator;
6534 ++m_it.primitive_iterator;
6545 auto result = *
this;
6553 assert(m_object !=
nullptr);
6555 switch (m_object->m_type)
6559 --m_it.object_iterator;
6565 --m_it.array_iterator;
6571 --m_it.primitive_iterator;
6583 if (m_object != other.m_object)
6585 throw std::domain_error(
"cannot compare iterators of different containers");
6588 assert(m_object !=
nullptr);
6590 switch (m_object->m_type)
6594 return (m_it.object_iterator == other.m_it.object_iterator);
6599 return (m_it.array_iterator == other.m_it.array_iterator);
6604 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6612 return not operator==(other);
6619 if (m_object != other.m_object)
6621 throw std::domain_error(
"cannot compare iterators of different containers");
6624 assert(m_object !=
nullptr);
6626 switch (m_object->m_type)
6630 throw std::domain_error(
"cannot compare order of object iterators");
6635 return (m_it.array_iterator < other.m_it.array_iterator);
6640 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6648 return not other.operator < (*this);
6654 return not operator<=(other);
6660 return not operator<(other);
6666 assert(m_object !=
nullptr);
6668 switch (m_object->m_type)
6672 throw std::domain_error(
"cannot use offsets with object iterators");
6677 m_it.array_iterator += i;
6683 m_it.primitive_iterator += i;
6694 return operator+=(-i);
6700 auto result = *
this;
6708 auto result = *
this;
6716 assert(m_object !=
nullptr);
6718 switch (m_object->m_type)
6722 throw std::domain_error(
"cannot use offsets with object iterators");
6727 return m_it.array_iterator - other.m_it.array_iterator;
6732 return m_it.primitive_iterator - other.m_it.primitive_iterator;
6740 assert(m_object !=
nullptr);
6742 switch (m_object->m_type)
6746 throw std::domain_error(
"cannot use operator[] for object iterators");
6751 return *(m_it.array_iterator + n);
6756 throw std::out_of_range(
"cannot get value");
6761 if (m_it.primitive_iterator == -n)
6767 throw std::out_of_range(
"cannot get value");
6774 typename object_t::key_type
key()
const 6776 assert(m_object !=
nullptr);
6778 if (m_object->is_object())
6780 return m_it.object_iterator->first;
6784 throw std::domain_error(
"cannot use key() for non-object iterators");
6798 internal_iterator m_it = internal_iterator();
6835 std::is_nothrow_move_constructible<pointer>::value and
6836 std::is_nothrow_move_assignable<pointer>::value and
6837 std::is_nothrow_move_constructible<internal_iterator>::value and
6838 std::is_nothrow_move_assignable<internal_iterator>::value
6841 base_iterator::operator=(other);
6848 return const_cast<reference>(base_iterator::operator*());
6854 return const_cast<pointer>(base_iterator::operator->());
6861 base_iterator::operator++();
6868 base_iterator::operator++();
6876 base_iterator::operator--();
6883 base_iterator::operator--();
6890 base_iterator::operator+=(i);
6897 base_iterator::operator-=(i);
6904 auto result = *
this;
6912 auto result = *
this;
6920 return base_iterator::operator-(other);
6926 return const_cast<reference>(base_iterator::operator[](n));
6932 return const_cast<reference>(base_iterator::value());
6953 template<
typename Base>
6975 return base_iterator::operator++(1);
6981 base_iterator::operator++();
6988 return base_iterator::operator--(1);
6994 base_iterator::operator--();
7001 base_iterator::operator+=(i);
7008 auto result = *
this;
7016 auto result = *
this;
7024 return this->base() - other.base();
7030 return *(this->operator+(n));
7034 typename object_t::key_type
key()
const 7036 auto it = --this->base();
7043 auto it = --this->base();
7044 return it.operator * ();
7065 enum class token_type
7084 using lexer_char_t =
unsigned char;
7087 explicit lexer(
const string_t& s) noexcept
7088 : m_stream(
nullptr), m_buffer(s)
7090 m_content =
reinterpret_cast<const lexer_char_t*
>(s.c_str());
7091 assert(m_content !=
nullptr);
7092 m_start = m_cursor = m_content;
7093 m_limit = m_content + s.size();
7097 explicit lexer(std::istream* s) noexcept
7098 : m_stream(s), m_buffer()
7100 assert(m_stream !=
nullptr);
7101 getline(*m_stream, m_buffer);
7102 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
7103 assert(m_content !=
nullptr);
7104 m_start = m_cursor = m_content;
7105 m_limit = m_content + m_buffer.size();
7112 lexer(
const lexer&) =
delete;
7113 lexer operator=(
const lexer&) =
delete;
7130 static string_t to_unicode(
const std::size_t codepoint1,
7131 const std::size_t codepoint2 = 0)
7134 std::size_t codepoint = codepoint1;
7137 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7140 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7154 throw std::invalid_argument(
"missing or wrong low surrogate");
7160 if (codepoint < 0x80)
7163 result.append(1, static_cast<typename string_t::value_type>(codepoint));
7165 else if (codepoint <= 0x7ff)
7168 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7169 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7171 else if (codepoint <= 0xffff)
7174 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7175 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7176 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7178 else if (codepoint <= 0x10ffff)
7181 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7182 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7183 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7184 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7188 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
7195 static std::string token_type_name(token_type t)
7199 case token_type::uninitialized:
7200 return "<uninitialized>";
7201 case token_type::literal_true:
7202 return "true literal";
7203 case token_type::literal_false:
7204 return "false literal";
7205 case token_type::literal_null:
7206 return "null literal";
7207 case token_type::value_string:
7208 return "string literal";
7209 case token_type::value_number:
7210 return "number literal";
7211 case token_type::begin_array:
7213 case token_type::begin_object:
7215 case token_type::end_array:
7217 case token_type::end_object:
7219 case token_type::name_separator:
7221 case token_type::value_separator:
7223 case token_type::parse_error:
7224 return "<parse error>";
7225 case token_type::end_of_input:
7226 return "end of input";
7230 return "unknown token";
7245 token_type scan() noexcept
7252 assert(m_start !=
nullptr);
7257 unsigned int yyaccept = 0;
7258 static const unsigned char yybm[] =
7260 0, 0, 0, 0, 0, 0, 0, 0,
7261 0, 32, 32, 0, 0, 32, 0, 0,
7262 128, 128, 128, 128, 128, 128, 128, 128,
7263 128, 128, 128, 128, 128, 128, 128, 128,
7264 160, 128, 0, 128, 128, 128, 128, 128,
7265 128, 128, 128, 128, 128, 128, 128, 128,
7266 192, 192, 192, 192, 192, 192, 192, 192,
7267 192, 192, 128, 128, 128, 128, 128, 128,
7268 128, 128, 128, 128, 128, 128, 128, 128,
7269 128, 128, 128, 128, 128, 128, 128, 128,
7270 128, 128, 128, 128, 128, 128, 128, 128,
7271 128, 128, 128, 128, 0, 128, 128, 128,
7272 128, 128, 128, 128, 128, 128, 128, 128,
7273 128, 128, 128, 128, 128, 128, 128, 128,
7274 128, 128, 128, 128, 128, 128, 128, 128,
7275 128, 128, 128, 128, 128, 128, 128, 128,
7276 128, 128, 128, 128, 128, 128, 128, 128,
7277 128, 128, 128, 128, 128, 128, 128, 128,
7278 128, 128, 128, 128, 128, 128, 128, 128,
7279 128, 128, 128, 128, 128, 128, 128, 128,
7280 128, 128, 128, 128, 128, 128, 128, 128,
7281 128, 128, 128, 128, 128, 128, 128, 128,
7282 128, 128, 128, 128, 128, 128, 128, 128,
7283 128, 128, 128, 128, 128, 128, 128, 128,
7284 128, 128, 128, 128, 128, 128, 128, 128,
7285 128, 128, 128, 128, 128, 128, 128, 128,
7286 128, 128, 128, 128, 128, 128, 128, 128,
7287 128, 128, 128, 128, 128, 128, 128, 128,
7288 128, 128, 128, 128, 128, 128, 128, 128,
7289 128, 128, 128, 128, 128, 128, 128, 128,
7290 128, 128, 128, 128, 128, 128, 128, 128,
7291 128, 128, 128, 128, 128, 128, 128, 128,
7293 if ((m_limit - m_cursor) < 5)
7298 if (yybm[0 + yych] & 32)
7300 goto basic_json_parser_6;
7310 goto basic_json_parser_2;
7314 goto basic_json_parser_4;
7316 goto basic_json_parser_9;
7322 goto basic_json_parser_4;
7326 goto basic_json_parser_10;
7328 goto basic_json_parser_12;
7337 goto basic_json_parser_4;
7341 goto basic_json_parser_13;
7343 goto basic_json_parser_15;
7349 goto basic_json_parser_17;
7353 goto basic_json_parser_19;
7355 goto basic_json_parser_4;
7367 goto basic_json_parser_21;
7371 goto basic_json_parser_4;
7373 goto basic_json_parser_23;
7379 goto basic_json_parser_24;
7383 goto basic_json_parser_4;
7385 goto basic_json_parser_25;
7394 goto basic_json_parser_26;
7396 goto basic_json_parser_4;
7402 goto basic_json_parser_28;
7406 goto basic_json_parser_30;
7408 goto basic_json_parser_4;
7412 basic_json_parser_2:
7415 return token_type::end_of_input;
7417 basic_json_parser_4:
7419 basic_json_parser_5:
7421 return token_type::parse_error;
7423 basic_json_parser_6:
7425 if (m_limit <= m_cursor)
7430 if (yybm[0 + yych] & 32)
7432 goto basic_json_parser_6;
7437 basic_json_parser_9:
7439 yych = *(m_marker = ++m_cursor);
7442 goto basic_json_parser_5;
7444 goto basic_json_parser_32;
7445 basic_json_parser_10:
7448 return token_type::value_separator;
7450 basic_json_parser_12:
7454 goto basic_json_parser_5;
7458 goto basic_json_parser_13;
7462 goto basic_json_parser_15;
7464 goto basic_json_parser_5;
7465 basic_json_parser_13:
7467 yych = *(m_marker = ++m_cursor);
7472 goto basic_json_parser_37;
7479 goto basic_json_parser_38;
7483 goto basic_json_parser_38;
7486 basic_json_parser_14:
7488 return token_type::value_number;
7490 basic_json_parser_15:
7492 m_marker = ++m_cursor;
7493 if ((m_limit - m_cursor) < 3)
7498 if (yybm[0 + yych] & 64)
7500 goto basic_json_parser_15;
7506 goto basic_json_parser_37;
7508 goto basic_json_parser_14;
7514 goto basic_json_parser_38;
7518 goto basic_json_parser_38;
7520 goto basic_json_parser_14;
7522 basic_json_parser_17:
7525 return token_type::name_separator;
7527 basic_json_parser_19:
7530 return token_type::begin_array;
7532 basic_json_parser_21:
7535 return token_type::end_array;
7537 basic_json_parser_23:
7539 yych = *(m_marker = ++m_cursor);
7542 goto basic_json_parser_39;
7544 goto basic_json_parser_5;
7545 basic_json_parser_24:
7547 yych = *(m_marker = ++m_cursor);
7550 goto basic_json_parser_40;
7552 goto basic_json_parser_5;
7553 basic_json_parser_25:
7555 yych = *(m_marker = ++m_cursor);
7558 goto basic_json_parser_41;
7560 goto basic_json_parser_5;
7561 basic_json_parser_26:
7564 return token_type::begin_object;
7566 basic_json_parser_28:
7569 return token_type::end_object;
7571 basic_json_parser_30:
7573 yych = *(m_marker = ++m_cursor);
7576 goto basic_json_parser_42;
7578 goto basic_json_parser_5;
7579 basic_json_parser_31:
7581 if (m_limit <= m_cursor)
7586 basic_json_parser_32:
7587 if (yybm[0 + yych] & 128)
7589 goto basic_json_parser_31;
7593 goto basic_json_parser_33;
7597 goto basic_json_parser_34;
7599 goto basic_json_parser_36;
7600 basic_json_parser_33:
7601 m_cursor = m_marker;
7604 goto basic_json_parser_5;
7608 goto basic_json_parser_14;
7610 basic_json_parser_34:
7613 return token_type::value_string;
7615 basic_json_parser_36:
7617 if (m_limit <= m_cursor)
7628 goto basic_json_parser_31;
7632 goto basic_json_parser_33;
7634 goto basic_json_parser_31;
7642 goto basic_json_parser_33;
7644 goto basic_json_parser_31;
7650 goto basic_json_parser_31;
7652 goto basic_json_parser_33;
7662 goto basic_json_parser_31;
7666 goto basic_json_parser_31;
7668 goto basic_json_parser_33;
7676 goto basic_json_parser_31;
7678 goto basic_json_parser_33;
7684 goto basic_json_parser_31;
7688 goto basic_json_parser_43;
7690 goto basic_json_parser_33;
7694 basic_json_parser_37:
7698 goto basic_json_parser_33;
7702 goto basic_json_parser_44;
7704 goto basic_json_parser_33;
7705 basic_json_parser_38:
7711 goto basic_json_parser_46;
7713 goto basic_json_parser_33;
7719 goto basic_json_parser_46;
7723 goto basic_json_parser_33;
7727 goto basic_json_parser_47;
7729 goto basic_json_parser_33;
7731 basic_json_parser_39:
7735 goto basic_json_parser_49;
7737 goto basic_json_parser_33;
7738 basic_json_parser_40:
7742 goto basic_json_parser_50;
7744 goto basic_json_parser_33;
7745 basic_json_parser_41:
7749 goto basic_json_parser_51;
7751 goto basic_json_parser_33;
7752 basic_json_parser_42:
7756 goto basic_json_parser_52;
7758 goto basic_json_parser_33;
7759 basic_json_parser_43:
7761 if (m_limit <= m_cursor)
7770 goto basic_json_parser_33;
7774 goto basic_json_parser_54;
7776 goto basic_json_parser_33;
7782 goto basic_json_parser_54;
7786 goto basic_json_parser_33;
7790 goto basic_json_parser_54;
7792 goto basic_json_parser_33;
7794 basic_json_parser_44:
7796 m_marker = ++m_cursor;
7797 if ((m_limit - m_cursor) < 3)
7806 goto basic_json_parser_14;
7810 goto basic_json_parser_44;
7812 goto basic_json_parser_14;
7818 goto basic_json_parser_38;
7822 goto basic_json_parser_38;
7824 goto basic_json_parser_14;
7826 basic_json_parser_46:
7830 goto basic_json_parser_33;
7834 goto basic_json_parser_33;
7836 basic_json_parser_47:
7838 if (m_limit <= m_cursor)
7845 goto basic_json_parser_14;
7849 goto basic_json_parser_47;
7851 goto basic_json_parser_14;
7852 basic_json_parser_49:
7856 goto basic_json_parser_55;
7858 goto basic_json_parser_33;
7859 basic_json_parser_50:
7863 goto basic_json_parser_56;
7865 goto basic_json_parser_33;
7866 basic_json_parser_51:
7870 goto basic_json_parser_58;
7872 goto basic_json_parser_33;
7873 basic_json_parser_52:
7878 basic_json_parser_54:
7880 if (m_limit <= m_cursor)
7889 goto basic_json_parser_33;
7893 goto basic_json_parser_60;
7895 goto basic_json_parser_33;
7901 goto basic_json_parser_60;
7905 goto basic_json_parser_33;
7909 goto basic_json_parser_60;
7911 goto basic_json_parser_33;
7913 basic_json_parser_55:
7917 goto basic_json_parser_61;
7919 goto basic_json_parser_33;
7920 basic_json_parser_56:
7923 return token_type::literal_null;
7925 basic_json_parser_58:
7928 return token_type::literal_true;
7930 basic_json_parser_60:
7932 if (m_limit <= m_cursor)
7941 goto basic_json_parser_33;
7945 goto basic_json_parser_63;
7947 goto basic_json_parser_33;
7953 goto basic_json_parser_63;
7957 goto basic_json_parser_33;
7961 goto basic_json_parser_63;
7963 goto basic_json_parser_33;
7965 basic_json_parser_61:
7968 return token_type::literal_false;
7970 basic_json_parser_63:
7972 if (m_limit <= m_cursor)
7981 goto basic_json_parser_33;
7985 goto basic_json_parser_31;
7987 goto basic_json_parser_33;
7993 goto basic_json_parser_31;
7997 goto basic_json_parser_33;
8001 goto basic_json_parser_31;
8003 goto basic_json_parser_33;
8010 void yyfill() noexcept
8012 if (m_stream ==
nullptr or not * m_stream)
8017 const auto offset_start = m_start - m_content;
8018 const auto offset_marker = m_marker - m_start;
8019 const auto offset_cursor = m_cursor - m_start;
8021 m_buffer.erase(0, static_cast<size_t>(offset_start));
8023 assert(m_stream !=
nullptr);
8024 std::getline(*m_stream, line);
8025 m_buffer +=
"\n" + line;
8027 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
8028 assert(m_content !=
nullptr);
8029 m_start = m_content;
8030 m_marker = m_start + offset_marker;
8031 m_cursor = m_start + offset_cursor;
8032 m_limit = m_start + m_buffer.size() - 1;
8038 assert(m_start !=
nullptr);
8039 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8040 static_cast<size_t>(m_cursor - m_start));
8067 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8070 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8126 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8127 4).c_str(),
nullptr, 16);
8130 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8133 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
8135 throw std::invalid_argument(
"missing low surrogate");
8139 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8140 (i + 7), 4).c_str(),
nullptr, 16);
8141 result += to_unicode(codepoint, codepoint2);
8148 result += to_unicode(codepoint);
8160 result.append(1, static_cast<typename string_t::value_type>(*i));
8187 long double str_to_float_t(
long double* ,
char** endptr)
const 8189 return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8207 double str_to_float_t(
double* ,
char** endptr)
const 8209 return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8227 float str_to_float_t(
float* ,
char** endptr)
const 8229 return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8244 template <
typename T_A,
typename T_B>
8245 static bool attempt_cast(T_A source, T_B& dest)
8247 dest =
static_cast<T_B
>(source);
8248 return (source == static_cast<T_A>(dest));
8289 void get_number(basic_json& result)
const 8291 typename string_t::value_type* endptr;
8292 assert(m_start !=
nullptr);
8297 if (*reinterpret_cast<typename string_t::const_pointer>(m_start) !=
'-')
8301 if (attempt_cast(std::strtoull(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr,
8302 10), result.m_value.number_unsigned))
8304 result.m_type = value_t::number_unsigned;
8309 result.m_type = value_t::number_float;
8316 if (attempt_cast(std::strtoll(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr,
8317 10), result.m_value.number_integer))
8319 result.m_type = value_t::number_integer;
8324 result.m_type = value_t::number_float;
8330 if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor || errno == ERANGE)
8332 result.m_type = value_t::number_float;
8335 if (result.m_type == value_t::number_float)
8342 result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(
nullptr), &endptr);
8345 if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor)
8347 throw std::invalid_argument(std::string(
"parse error - ") + get_token() +
" is not a number");
8354 std::istream* m_stream =
nullptr;
8358 const lexer_char_t* m_content =
nullptr;
8360 const lexer_char_t* m_start =
nullptr;
8362 const lexer_char_t* m_marker =
nullptr;
8364 const lexer_char_t* m_cursor =
nullptr;
8366 const lexer_char_t* m_limit =
nullptr;
8379 : callback(cb), m_lexer(s)
8387 : callback(cb), m_lexer(&_is)
8396 basic_json result = parse_internal(
true);
8398 expect(lexer::token_type::end_of_input);
8407 basic_json parse_internal(
bool keep)
8409 auto result = basic_json(value_t::discarded);
8413 case lexer::token_type::begin_object:
8415 if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
8418 result.m_type = value_t::object;
8419 result.m_value = json_value(value_t::object);
8426 if (last_token == lexer::token_type::end_object)
8429 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8431 result = basic_json(value_t::discarded);
8437 unexpect(lexer::token_type::value_separator);
8443 if (last_token == lexer::token_type::value_separator)
8449 expect(lexer::token_type::value_string);
8450 const auto key = m_lexer.get_string();
8452 bool keep_tag =
false;
8458 keep_tag = callback(depth, parse_event_t::key, k);
8468 expect(lexer::token_type::name_separator);
8472 auto value = parse_internal(keep);
8473 if (keep and keep_tag and not value.is_discarded())
8475 result[key] = std::move(value);
8478 while (last_token == lexer::token_type::value_separator);
8481 expect(lexer::token_type::end_object);
8483 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8485 result = basic_json(value_t::discarded);
8491 case lexer::token_type::begin_array:
8493 if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
8496 result.m_type = value_t::array;
8497 result.m_value = json_value(value_t::array);
8504 if (last_token == lexer::token_type::end_array)
8507 if (callback and not callback(--depth, parse_event_t::array_end, result))
8509 result = basic_json(value_t::discarded);
8515 unexpect(lexer::token_type::value_separator);
8521 if (last_token == lexer::token_type::value_separator)
8527 auto value = parse_internal(keep);
8528 if (keep and not value.is_discarded())
8530 result.push_back(std::move(value));
8533 while (last_token == lexer::token_type::value_separator);
8536 expect(lexer::token_type::end_array);
8538 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8540 result = basic_json(value_t::discarded);
8546 case lexer::token_type::literal_null:
8549 result.m_type = value_t::null;
8553 case lexer::token_type::value_string:
8555 const auto s = m_lexer.get_string();
8557 result = basic_json(s);
8561 case lexer::token_type::literal_true:
8564 result.m_type = value_t::boolean;
8565 result.m_value =
true;
8569 case lexer::token_type::literal_false:
8572 result.m_type = value_t::boolean;
8573 result.m_value =
false;
8577 case lexer::token_type::value_number:
8579 m_lexer.get_number(result);
8587 unexpect(last_token);
8591 if (keep and callback and not callback(depth, parse_event_t::value, result))
8593 result = basic_json(value_t::discarded);
8599 typename lexer::token_type get_token() noexcept
8601 last_token = m_lexer.scan();
8605 void expect(
typename lexer::token_type t)
const 8607 if (t != last_token)
8609 std::string error_msg =
"parse error - unexpected ";
8610 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token() +
"'") :
8611 lexer::token_type_name(last_token));
8612 error_msg +=
"; expected " + lexer::token_type_name(t);
8613 throw std::invalid_argument(error_msg);
8617 void unexpect(
typename lexer::token_type t)
const 8619 if (t == last_token)
8621 std::string error_msg =
"parse error - unexpected ";
8622 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token() +
"'") :
8623 lexer::token_type_name(last_token));
8624 throw std::invalid_argument(error_msg);
8634 typename lexer::token_type last_token = lexer::token_type::uninitialized;
8672 is_nothrow_move_constructible<nlohmann::json>::value and
8673 is_nothrow_move_assignable<nlohmann::json>::value
8691 const auto& h = hash<nlohmann::json::string_t>();
8709 inline nlohmann::json operator "" _json(
const char* s, std::size_t)
8715 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 8716 #pragma GCC diagnostic pop reference operator*()
return a reference to the value pointed to by the iterator
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
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
basic_json<> json
default JSON class
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)
pointer operator->()
dereference the iterator
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
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
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)
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
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
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.