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;
165 template<
typename U,
typename V,
typename... Args>
class ObjectType = std::map,
166 template<
typename U,
typename... Args>
class ArrayType = std::vector,
167 class StringType = std::string,
168 class BooleanType = bool,
169 class NumberIntegerType = std::int64_t,
170 class NumberUnsignedType = std::uint64_t,
171 class NumberFloatType = double,
172 template<
typename U>
class AllocatorType = std::allocator
213 using pointer =
typename std::allocator_traits<allocator_type>::pointer;
215 using const_pointer =
typename std::allocator_traits<allocator_type>::const_pointer;
330 using object_t = ObjectType<StringType,
332 std::less<StringType>,
333 AllocatorType<std::pair<
const StringType,
380 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
699 template<
typename T,
typename... Args>
700 static T* create(Args&& ... args)
702 AllocatorType<T> alloc;
703 auto deleter = [&](T * object)
705 alloc.deallocate(
object, 1);
707 std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
708 alloc.construct(
object.
get(), std::forward<Args>(args)...);
709 return object.release();
741 json_value() =
default;
743 json_value(
boolean_t v) noexcept : boolean(v) {}
755 case value_t::object:
757 object = create<object_t>();
763 array = create<array_t>();
767 case value_t::string:
769 string = create<string_t>(
"");
773 case value_t::boolean:
779 case value_t::number_integer:
785 case value_t::number_unsigned:
791 case value_t::number_float:
807 string = create<string_t>(value);
813 object = create<object_t>(value);
817 json_value(
const array_t& value)
819 array = create<array_t>(value);
902 using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
952 : m_type(value_type), m_value(value_type)
979 basic_json() =
default;
1027 : m_type(
value_t::object), m_value(val)
1056 template <
class CompatibleObjectType,
typename 1058 std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1059 std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value,
int>::type
1066 m_value.object = create<object_t>(begin(val), end(val));
1089 : m_type(
value_t::array), m_value(val)
1118 template <
class CompatibleArrayType,
typename 1120 not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1121 not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1122 not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1123 not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1124 not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1125 not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1126 std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value,
int>::type
1133 m_value.array = create<array_t>(begin(val), end(val));
1158 : m_type(
value_t::string), m_value(val)
1208 template <
class CompatibleStringType,
typename 1210 std::is_constructible<string_t, CompatibleStringType>::value,
int>::type
1231 : m_type(value_t::boolean), m_value(val)
1257 template<
typename T,
1258 typename std::enable_if<
1259 not (std::is_same<T, int>::value)
1260 and std::is_same<T, number_integer_t>::value
1264 : m_type(value_t::number_integer), m_value(val)
1293 : m_type(value_t::number_integer),
1294 m_value(static_cast<number_integer_t>(val))
1322 template<
typename CompatibleNumberIntegerType,
typename 1324 std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1325 std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1326 std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1327 CompatibleNumberIntegerType>::type
1330 : m_type(value_t::number_integer),
1331 m_value(static_cast<number_integer_t>(val))
1351 template<
typename T,
1352 typename std::enable_if<
1353 not (std::is_same<T, int>::value)
1354 and std::is_same<T, number_unsigned_t>::value
1358 : m_type(value_t::number_unsigned), m_value(val)
1381 template <
typename CompatibleNumberUnsignedType,
typename 1383 std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1384 std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1385 !std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1386 CompatibleNumberUnsignedType >::type
1389 : m_type(value_t::number_unsigned),
1390 m_value(static_cast<number_unsigned_t>(val))
1418 : m_type(value_t::number_float), m_value(val)
1421 if (not std::isfinite(val))
1423 m_type = value_t::null;
1424 m_value = json_value();
1458 template<
typename CompatibleNumberFloatType,
typename =
typename 1460 std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1461 std::is_floating_point<CompatibleNumberFloatType>::value>::type
1537 bool type_deduction =
true,
1538 value_t manual_type = value_t::array)
1541 bool is_an_object =
true;
1545 for (
const auto& element : init)
1547 if (not element.is_array() or element.size() != 2
1548 or not element[0].is_string())
1552 is_an_object =
false;
1558 if (not type_deduction)
1561 if (manual_type == value_t::array)
1563 is_an_object =
false;
1567 if (manual_type == value_t::object and not is_an_object)
1569 throw std::domain_error(
"cannot create object from initializer list");
1576 m_type = value_t::object;
1577 m_value = value_t::object;
1579 assert(m_value.object !=
nullptr);
1581 for (
auto& element : init)
1583 m_value.object->emplace(*(element[0].m_value.string), element[1]);
1589 m_type = value_t::array;
1590 m_value.array = create<array_t>(init);
1628 static basic_json
array(std::initializer_list<basic_json> init =
1629 std::initializer_list<basic_json>())
1631 return basic_json(init,
false, value_t::array);
1668 static basic_json
object(std::initializer_list<basic_json> init =
1669 std::initializer_list<basic_json>())
1671 return basic_json(init,
false, value_t::object);
1695 m_value.array = create<array_t>(cnt, val);
1732 template <
class InputIT,
typename 1734 std::is_same<InputIT, typename basic_json_t::iterator>::value or
1735 std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1738 basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1741 if (first.m_object != last.m_object)
1743 throw std::domain_error(
"iterators are not compatible");
1749 case value_t::boolean:
1750 case value_t::number_float:
1751 case value_t::number_integer:
1752 case value_t::number_unsigned:
1753 case value_t::string:
1755 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1757 throw std::out_of_range(
"iterators out of range");
1770 case value_t::number_integer:
1772 assert(first.m_object !=
nullptr);
1773 m_value.number_integer = first.m_object->m_value.number_integer;
1777 case value_t::number_unsigned:
1779 assert(first.m_object !=
nullptr);
1780 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1784 case value_t::number_float:
1786 assert(first.m_object !=
nullptr);
1787 m_value.number_float = first.m_object->m_value.number_float;
1791 case value_t::boolean:
1793 assert(first.m_object !=
nullptr);
1794 m_value.boolean = first.m_object->m_value.boolean;
1798 case value_t::string:
1800 assert(first.m_object !=
nullptr);
1801 m_value = *first.m_object->m_value.string;
1805 case value_t::object:
1807 m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1811 case value_t::array:
1813 m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1819 assert(first.m_object !=
nullptr);
1820 throw std::domain_error(
"cannot use construct with iterators from " + first.m_object->type_name());
1847 *
this = parser(i, cb).parse();
1877 : m_type(other.m_type)
1881 case value_t::object:
1883 assert(other.m_value.object !=
nullptr);
1884 m_value = *other.m_value.object;
1888 case value_t::array:
1890 assert(other.m_value.array !=
nullptr);
1891 m_value = *other.m_value.array;
1895 case value_t::string:
1897 assert(other.m_value.string !=
nullptr);
1898 m_value = *other.m_value.string;
1902 case value_t::boolean:
1904 m_value = other.m_value.boolean;
1908 case value_t::number_integer:
1910 m_value = other.m_value.number_integer;
1914 case value_t::number_unsigned:
1916 m_value = other.m_value.number_unsigned;
1920 case value_t::number_float:
1922 m_value = other.m_value.number_float;
1952 : m_type(
std::move(other.m_type)),
1953 m_value(
std::move(other.m_value))
1956 other.m_type = value_t::null;
1984 std::is_nothrow_move_constructible<value_t>::value and
1985 std::is_nothrow_move_assignable<value_t>::value and
1986 std::is_nothrow_move_constructible<json_value>::value and
1987 std::is_nothrow_move_assignable<json_value>::value
1991 swap(m_type, other.m_type);
1992 swap(m_value, other.m_value);
2015 case value_t::object:
2017 AllocatorType<object_t> alloc;
2018 alloc.destroy(m_value.object);
2019 alloc.deallocate(m_value.object, 1);
2023 case value_t::array:
2025 AllocatorType<array_t> alloc;
2026 alloc.destroy(m_value.array);
2027 alloc.deallocate(m_value.array, 1);
2031 case value_t::string:
2033 AllocatorType<string_t> alloc;
2034 alloc.destroy(m_value.string);
2035 alloc.deallocate(m_value.string, 1);
2082 std::stringstream ss;
2086 dump(ss,
true, static_cast<unsigned int>(indent));
2146 return is_null() or is_string() or is_boolean() or is_number();
2173 return is_array() or is_object();
2195 return m_type == value_t::null;
2217 return m_type == value_t::boolean;
2247 return is_number_integer() or is_number_float();
2276 return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2304 return m_type == value_t::number_unsigned;
2332 return m_type == value_t::number_float;
2354 return m_type == value_t::object;
2376 return m_type == value_t::array;
2398 return m_type == value_t::string;
2425 return m_type == value_t::discarded;
2459 template <
class T,
typename 2461 std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2462 std::is_convertible<basic_json_t, typename T::mapped_type>::value
2464 T get_impl(T*)
const 2468 assert(m_value.object !=
nullptr);
2469 return T(m_value.object->begin(), m_value.object->end());
2473 throw std::domain_error(
"type must be object, but is " + type_name());
2482 assert(m_value.object !=
nullptr);
2483 return *(m_value.object);
2487 throw std::domain_error(
"type must be object, but is " + type_name());
2492 template <
class T,
typename 2494 std::is_convertible<basic_json_t, typename T::value_type>::value and
2495 not std::is_same<basic_json_t, typename T::value_type>::value and
2496 not std::is_arithmetic<T>::value and
2497 not std::is_convertible<std::string, T>::value and
2498 not has_mapped_type<T>::value
2500 T get_impl(T*)
const 2505 assert(m_value.array !=
nullptr);
2506 std::transform(m_value.array->begin(), m_value.array->end(),
2507 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2509 return i.
get<
typename T::value_type>();
2515 throw std::domain_error(
"type must be array, but is " + type_name());
2520 template <
class T,
typename 2522 std::is_convertible<basic_json_t, T>::value and
2523 not std::is_same<basic_json_t, T>::value
2525 std::vector<T> get_impl(std::vector<T>*)
const 2529 std::vector<T> to_vector;
2530 assert(m_value.array !=
nullptr);
2531 to_vector.reserve(m_value.array->size());
2532 std::transform(m_value.array->begin(), m_value.array->end(),
2533 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2541 throw std::domain_error(
"type must be array, but is " + type_name());
2546 template <
class T,
typename 2548 std::is_same<basic_json, typename T::value_type>::value and
2549 not has_mapped_type<T>::value
2551 T get_impl(T*)
const 2555 assert(m_value.array !=
nullptr);
2556 return T(m_value.array->begin(), m_value.array->end());
2560 throw std::domain_error(
"type must be array, but is " + type_name());
2569 assert(m_value.array !=
nullptr);
2570 return *(m_value.array);
2574 throw std::domain_error(
"type must be array, but is " + type_name());
2579 template <
typename T,
typename 2581 std::is_convertible<string_t, T>::value
2583 T get_impl(T*)
const 2587 assert(m_value.string !=
nullptr);
2588 return *m_value.string;
2592 throw std::domain_error(
"type must be string, but is " + type_name());
2597 template<
typename T,
typename 2599 std::is_arithmetic<T>::value
2601 T get_impl(T*)
const 2605 case value_t::number_integer:
2607 return static_cast<T
>(m_value.number_integer);
2610 case value_t::number_unsigned:
2612 return static_cast<T
>(m_value.number_unsigned);
2615 case value_t::number_float:
2617 return static_cast<T
>(m_value.number_float);
2622 throw std::domain_error(
"type must be number, but is " + type_name());
2632 :
throw std::domain_error(
"type must be boolean, but is " + type_name());
2638 return is_object() ? m_value.object :
nullptr;
2644 return is_object() ? m_value.object :
nullptr;
2650 return is_array() ? m_value.array :
nullptr;
2654 constexpr
const array_t* get_impl_ptr(
const array_t*)
const noexcept
2656 return is_array() ? m_value.array :
nullptr;
2662 return is_string() ? m_value.string :
nullptr;
2668 return is_string() ? m_value.string :
nullptr;
2674 return is_boolean() ? &m_value.boolean :
nullptr;
2680 return is_boolean() ? &m_value.boolean :
nullptr;
2686 return is_number_integer() ? &m_value.number_integer :
nullptr;
2692 return is_number_integer() ? &m_value.number_integer :
nullptr;
2698 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2704 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2710 return is_number_float() ? &m_value.number_float :
nullptr;
2716 return is_number_float() ? &m_value.number_float :
nullptr;
2730 template<
typename ReferenceType,
typename ThisType>
2731 static ReferenceType get_ref_impl(ThisType& obj)
2734 using PointerType =
typename std::add_pointer<ReferenceType>::type;
2735 auto ptr = obj.template get_ptr<PointerType>();
2743 throw std::domain_error(
"incompatible ReferenceType for get_ref, actual type is " +
2786 template<
typename ValueType,
typename 2788 not std::is_pointer<ValueType>::value
2790 ValueType
get()
const 2792 return get_impl(static_cast<ValueType*>(
nullptr));
2821 template<
typename PointerType,
typename 2823 std::is_pointer<PointerType>::value
2825 PointerType
get() noexcept
2828 return get_ptr<PointerType>();
2835 template<
typename PointerType,
typename 2837 std::is_pointer<PointerType>::value
2839 constexpr
const PointerType
get()
const noexcept
2842 return get_ptr<PointerType>();
2870 template<
typename PointerType,
typename 2872 std::is_pointer<PointerType>::value
2877 return get_impl_ptr(static_cast<PointerType>(
nullptr));
2884 template<
typename PointerType,
typename 2886 std::is_pointer<PointerType>::value
2887 and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2889 constexpr
const PointerType
get_ptr() const noexcept
2892 return get_impl_ptr(static_cast<const PointerType>(
nullptr));
2921 template<
typename ReferenceType,
typename 2923 std::is_reference<ReferenceType>::value
2928 return get_ref_impl<ReferenceType>(*this);
2935 template<
typename ReferenceType,
typename 2937 std::is_reference<ReferenceType>::value
2938 and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
2943 return get_ref_impl<ReferenceType>(*this);
2974 template <
typename ValueType,
typename 2976 not std::is_pointer<ValueType>::value
2977 and not std::is_same<ValueType, typename string_t::value_type>::value
2978 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015 2979 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
2982 operator ValueType()
const 2985 return get<ValueType>();
3027 assert(m_value.array !=
nullptr);
3028 return m_value.array->at(idx);
3030 catch (std::out_of_range&)
3033 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3038 throw std::domain_error(
"cannot use at() with " + type_name());
3071 assert(m_value.array !=
nullptr);
3072 return m_value.array->at(idx);
3074 catch (std::out_of_range&)
3077 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3082 throw std::domain_error(
"cannot use at() with " + type_name());
3119 assert(m_value.object !=
nullptr);
3120 return m_value.object->at(key);
3122 catch (std::out_of_range&)
3125 throw std::out_of_range(
"key '" + key +
"' not found");
3130 throw std::domain_error(
"cannot use at() with " + type_name());
3167 assert(m_value.object !=
nullptr);
3168 return m_value.object->at(key);
3170 catch (std::out_of_range&)
3173 throw std::out_of_range(
"key '" + key +
"' not found");
3178 throw std::domain_error(
"cannot use at() with " + type_name());
3212 m_type = value_t::array;
3213 m_value.
array = create<array_t>();
3220 assert(m_value.array !=
nullptr);
3221 for (
size_t i = m_value.array->size(); i <= idx; ++i)
3223 m_value.array->push_back(basic_json());
3226 return m_value.array->operator[](idx);
3230 throw std::domain_error(
"cannot use operator[] with " + type_name());
3258 assert(m_value.array !=
nullptr);
3259 return m_value.array->operator[](idx);
3263 throw std::domain_error(
"cannot use operator[] with " + type_name());
3299 m_type = value_t::object;
3300 m_value.
object = create<object_t>();
3306 assert(m_value.object !=
nullptr);
3307 return m_value.object->operator[](key);
3311 throw std::domain_error(
"cannot use operator[] with " + type_name());
3347 assert(m_value.object !=
nullptr);
3348 assert(m_value.object->find(key) != m_value.object->end());
3349 return m_value.object->find(key)->second;
3353 throw std::domain_error(
"cannot use operator[] with " + type_name());
3384 template<
typename T, std::
size_t n>
3387 return operator[](static_cast<const T>(key));
3419 template<
typename T, std::
size_t n>
3422 return operator[](static_cast<const T>(key));
3452 template<
typename T>
3458 m_type = value_t::object;
3459 m_value = value_t::object;
3465 assert(m_value.object !=
nullptr);
3466 return m_value.object->operator[](key);
3470 throw std::domain_error(
"cannot use operator[] with " + type_name());
3501 template<
typename T>
3507 assert(m_value.object !=
nullptr);
3508 assert(m_value.object->find(key) != m_value.object->end());
3509 return m_value.object->find(key)->second;
3513 throw std::domain_error(
"cannot use operator[] with " + type_name());
3565 template <
class ValueType,
typename 3567 std::is_convertible<basic_json_t, ValueType>::value
3569 ValueType
value(
const typename object_t::key_type& key, ValueType default_value)
const 3575 const auto it = find(key);
3582 return default_value;
3587 throw std::domain_error(
"cannot use value() with " + type_name());
3595 string_t value(
const typename object_t::key_type& key,
const char* default_value)
const 3597 return value(key,
string_t(default_value));
3728 template <
class InteratorType,
typename 3730 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3731 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3737 if (
this != pos.m_object)
3739 throw std::domain_error(
"iterator does not fit current value");
3742 InteratorType result = end();
3746 case value_t::boolean:
3747 case value_t::number_float:
3748 case value_t::number_integer:
3749 case value_t::number_unsigned:
3750 case value_t::string:
3752 if (not pos.m_it.primitive_iterator.is_begin())
3754 throw std::out_of_range(
"iterator out of range");
3759 delete m_value.string;
3760 m_value.string =
nullptr;
3763 m_type = value_t::null;
3767 case value_t::object:
3769 assert(m_value.object !=
nullptr);
3770 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3774 case value_t::array:
3776 assert(m_value.array !=
nullptr);
3777 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3783 throw std::domain_error(
"cannot use erase() with " + type_name());
3836 template <
class InteratorType,
typename 3838 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3839 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3842 InteratorType
erase(InteratorType first, InteratorType last)
3845 if (
this != first.m_object or
this != last.m_object)
3847 throw std::domain_error(
"iterators do not fit current value");
3850 InteratorType result = end();
3854 case value_t::boolean:
3855 case value_t::number_float:
3856 case value_t::number_integer:
3857 case value_t::number_unsigned:
3858 case value_t::string:
3860 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3862 throw std::out_of_range(
"iterators out of range");
3867 delete m_value.string;
3868 m_value.string =
nullptr;
3871 m_type = value_t::null;
3875 case value_t::object:
3877 assert(m_value.object !=
nullptr);
3878 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3879 last.m_it.object_iterator);
3883 case value_t::array:
3885 assert(m_value.array !=
nullptr);
3886 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3887 last.m_it.array_iterator);
3893 throw std::domain_error(
"cannot use erase() with " + type_name());
3934 assert(m_value.object !=
nullptr);
3935 return m_value.object->erase(key);
3939 throw std::domain_error(
"cannot use erase() with " + type_name());
3974 throw std::out_of_range(
"index out of range");
3977 assert(m_value.array !=
nullptr);
3978 m_value.array->erase(m_value.array->begin() +
static_cast<difference_type>(idx));
3982 throw std::domain_error(
"cannot use erase() with " + type_name());
4015 auto result = end();
4019 assert(m_value.object !=
nullptr);
4020 result.m_it.object_iterator = m_value.object->find(key);
4032 auto result = cend();
4036 assert(m_value.object !=
nullptr);
4037 result.m_it.object_iterator = m_value.object->find(key);
4064 assert(not is_object() or m_value.object !=
nullptr);
4065 return is_object() ? m_value.object->count(key) : 0;
4353 template<
typename IteratorType>
class iteration_proxy;
4369 return iteration_proxy<iterator>(cont);
4377 return iteration_proxy<const_iterator>(cont);
4433 case value_t::array:
4435 assert(m_value.array !=
nullptr);
4436 return m_value.array->empty();
4439 case value_t::object:
4441 assert(m_value.object !=
nullptr);
4442 return m_value.object->empty();
4496 case value_t::array:
4498 assert(m_value.array !=
nullptr);
4499 return m_value.array->size();
4502 case value_t::object:
4504 assert(m_value.object !=
nullptr);
4505 return m_value.object->size();
4556 case value_t::array:
4558 assert(m_value.array !=
nullptr);
4559 return m_value.array->max_size();
4562 case value_t::object:
4564 assert(m_value.object !=
nullptr);
4565 return m_value.object->max_size();
4615 case value_t::number_integer:
4617 m_value.number_integer = 0;
4621 case value_t::number_unsigned:
4623 m_value.number_unsigned = 0;
4627 case value_t::number_float:
4629 m_value.number_float = 0.0;
4633 case value_t::boolean:
4635 m_value.boolean =
false;
4639 case value_t::string:
4641 assert(m_value.string !=
nullptr);
4642 m_value.string->clear();
4646 case value_t::array:
4648 assert(m_value.array !=
nullptr);
4649 m_value.array->clear();
4653 case value_t::object:
4655 assert(m_value.object !=
nullptr);
4656 m_value.object->clear();
4690 if (not(is_null() or is_array()))
4692 throw std::domain_error(
"cannot use push_back() with " + type_name());
4698 m_type = value_t::array;
4699 m_value = value_t::array;
4703 assert(m_value.array !=
nullptr);
4704 m_value.array->push_back(std::move(val));
4706 val.m_type = value_t::null;
4715 push_back(std::move(val));
4726 if (not(is_null() or is_array()))
4728 throw std::domain_error(
"cannot use push_back() with " + type_name());
4734 m_type = value_t::array;
4735 m_value = value_t::array;
4739 assert(m_value.array !=
nullptr);
4740 m_value.array->push_back(val);
4776 if (not(is_null() or is_object()))
4778 throw std::domain_error(
"cannot use push_back() with " + type_name());
4784 m_type = value_t::object;
4785 m_value = value_t::object;
4789 assert(m_value.object !=
nullptr);
4790 m_value.object->insert(val);
4800 return operator[](val.first);
4831 if (pos.m_object !=
this)
4833 throw std::domain_error(
"iterator does not fit current value");
4838 assert(m_value.array !=
nullptr);
4839 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4844 throw std::domain_error(
"cannot use insert() with " + type_name());
4854 return insert(pos, val);
4887 if (pos.m_object !=
this)
4889 throw std::domain_error(
"iterator does not fit current value");
4894 assert(m_value.array !=
nullptr);
4895 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4900 throw std::domain_error(
"cannot use insert() with " + type_name());
4939 throw std::domain_error(
"cannot use insert() with " + type_name());
4943 if (pos.m_object !=
this)
4945 throw std::domain_error(
"iterator does not fit current value");
4948 if (first.m_object != last.m_object)
4950 throw std::domain_error(
"iterators do not fit");
4953 if (first.m_object ==
this or last.m_object ==
this)
4955 throw std::domain_error(
"passed iterators may not belong to container");
4960 assert(m_value.array !=
nullptr);
4961 result.m_it.array_iterator = m_value.array->insert(
4962 pos.m_it.array_iterator,
4963 first.m_it.array_iterator,
4964 last.m_it.array_iterator);
4997 throw std::domain_error(
"cannot use insert() with " + type_name());
5001 if (pos.m_object !=
this)
5003 throw std::domain_error(
"iterator does not fit current value");
5008 assert(m_value.array !=
nullptr);
5009 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5031 std::is_nothrow_move_constructible<value_t>::value and
5032 std::is_nothrow_move_assignable<value_t>::value and
5033 std::is_nothrow_move_constructible<json_value>::value and
5034 std::is_nothrow_move_assignable<json_value>::value
5037 std::swap(m_type, other.m_type);
5038 std::swap(m_value, other.m_value);
5066 assert(m_value.array !=
nullptr);
5067 std::swap(*(m_value.array), other);
5071 throw std::domain_error(
"cannot use swap() with " + type_name());
5100 assert(m_value.object !=
nullptr);
5101 std::swap(*(m_value.object), other);
5105 throw std::domain_error(
"cannot use swap() with " + type_name());
5134 assert(m_value.string !=
nullptr);
5135 std::swap(*(m_value.string), other);
5139 throw std::domain_error(
"cannot use swap() with " + type_name());
5165 static constexpr std::array<uint8_t, 8> order = {{
5178 if (lhs == value_t::discarded or rhs == value_t::discarded)
5183 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
5212 const auto lhs_type = lhs.type();
5213 const auto rhs_type = rhs.type();
5215 if (lhs_type == rhs_type)
5219 case value_t::array:
5221 assert(lhs.m_value.array !=
nullptr);
5222 assert(rhs.m_value.array !=
nullptr);
5223 return *lhs.m_value.array == *rhs.m_value.array;
5225 case value_t::object:
5227 assert(lhs.m_value.object !=
nullptr);
5228 assert(rhs.m_value.object !=
nullptr);
5229 return *lhs.m_value.object == *rhs.m_value.object;
5235 case value_t::string:
5237 assert(lhs.m_value.string !=
nullptr);
5238 assert(rhs.m_value.string !=
nullptr);
5239 return *lhs.m_value.string == *rhs.m_value.string;
5241 case value_t::boolean:
5243 return lhs.m_value.boolean == rhs.m_value.boolean;
5245 case value_t::number_integer:
5247 return lhs.m_value.number_integer == rhs.m_value.number_integer;
5249 case value_t::number_unsigned:
5251 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5253 case value_t::number_float:
5255 return lhs.m_value.number_float == rhs.m_value.number_float;
5263 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5265 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5267 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5269 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_integer);
5271 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5273 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5275 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5277 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5279 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5281 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5283 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5285 return lhs.m_value.number_integer ==
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5341 return not (lhs == rhs);
5373 return not v.is_null();
5402 const auto lhs_type = lhs.type();
5403 const auto rhs_type = rhs.type();
5405 if (lhs_type == rhs_type)
5409 case value_t::array:
5411 assert(lhs.m_value.array !=
nullptr);
5412 assert(rhs.m_value.array !=
nullptr);
5413 return *lhs.m_value.array < *rhs.m_value.array;
5415 case value_t::object:
5417 assert(lhs.m_value.object !=
nullptr);
5418 assert(rhs.m_value.object !=
nullptr);
5419 return *lhs.m_value.object < *rhs.m_value.object;
5425 case value_t::string:
5427 assert(lhs.m_value.string !=
nullptr);
5428 assert(rhs.m_value.string !=
nullptr);
5429 return *lhs.m_value.string < *rhs.m_value.string;
5431 case value_t::boolean:
5433 return lhs.m_value.boolean < rhs.m_value.boolean;
5435 case value_t::number_integer:
5437 return lhs.m_value.number_integer < rhs.m_value.number_integer;
5439 case value_t::number_unsigned:
5441 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5443 case value_t::number_float:
5445 return lhs.m_value.number_float < rhs.m_value.number_float;
5453 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5455 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5457 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5459 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_integer);
5461 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5463 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5465 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5467 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5469 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5471 return lhs.m_value.number_integer <
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5473 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5475 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5481 return operator<(lhs_type, rhs_type);
5503 return not (rhs < lhs);
5525 return not (lhs <= rhs);
5547 return not (lhs < rhs);
5582 friend std::ostream&
operator<<(std::ostream& o,
const basic_json& j)
5585 const bool pretty_print = (o.width() > 0);
5586 const auto indentation = (pretty_print ? o.width() : 0);
5592 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
5600 friend std::ostream&
operator>>(
const basic_json& j, std::ostream& o)
5641 return parser(s, cb).
parse();
5670 return parser(i, cb).
parse();
5678 return parser(i, cb).
parse();
5706 j = parser(i).
parse();
5716 j = parser(i).
parse();
5729 string_t type_name()
const noexcept
5735 case value_t::object:
5737 case value_t::array:
5739 case value_t::string:
5741 case value_t::boolean:
5743 case value_t::discarded:
5758 static std::size_t extra_space(
const string_t& s) noexcept
5760 std::size_t result = 0;
5762 for (
const auto& c : s)
5781 if (c >= 0x00 and c <= 0x1f)
5809 const auto space = extra_space(s);
5816 string_t result(s.size() + space,
'\\');
5817 std::size_t pos = 0;
5819 for (
const auto& c : s)
5826 result[pos + 1] =
'"';
5842 result[pos + 1] =
'b';
5850 result[pos + 1] =
'f';
5858 result[pos + 1] =
'n';
5866 result[pos + 1] =
'r';
5874 result[pos + 1] =
't';
5881 if (c >= 0x00 and c <= 0x1f)
5885 auto hexify = [](
const char v) ->
char 5887 return (v < 10) ? (
'0' + v) : (
'a' + v - 10);
5892 {
'u',
'0',
'0', hexify(c >> 4), hexify(c & 0x0f)
5930 void dump(std::ostream& o,
5931 const bool pretty_print,
5932 const unsigned int indent_step,
5933 const unsigned int current_indent = 0)
const 5936 unsigned int new_indent = current_indent;
5940 case value_t::object:
5942 assert(m_value.object !=
nullptr);
5944 if (m_value.object->empty())
5955 new_indent += indent_step;
5959 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5961 if (i != m_value.object->cbegin())
5963 o << (pretty_print ?
",\n" :
",");
5965 o <<
string_t(new_indent,
' ') <<
"\"" 5966 << escape_string(i->first) <<
"\":" 5967 << (pretty_print ?
" " :
"");
5968 i->second.dump(o, pretty_print, indent_step, new_indent);
5974 new_indent -= indent_step;
5978 o <<
string_t(new_indent,
' ') +
"}";
5982 case value_t::array:
5984 assert(m_value.array !=
nullptr);
5986 if (m_value.array->empty())
5997 new_indent += indent_step;
6001 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6003 if (i != m_value.array->cbegin())
6005 o << (pretty_print ?
",\n" :
",");
6008 i->dump(o, pretty_print, indent_step, new_indent);
6014 new_indent -= indent_step;
6018 o <<
string_t(new_indent,
' ') <<
"]";
6022 case value_t::string:
6024 assert(m_value.string !=
nullptr);
6025 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
6029 case value_t::boolean:
6031 o << (m_value.boolean ?
"true" :
"false");
6035 case value_t::number_integer:
6037 o << m_value.number_integer;
6041 case value_t::number_unsigned:
6043 o << m_value.number_unsigned;
6047 case value_t::number_float:
6055 if (std::fmod(m_value.number_float, 1) == 0)
6057 o << std::fixed << std::setprecision(1);
6062 o.unsetf(std::ios_base::floatfield);
6063 o << std::setprecision(std::numeric_limits<double>::digits10);
6065 o << m_value.number_float;
6069 case value_t::discarded:
6089 value_t m_type = value_t::null;
6092 json_value m_value = {};
6109 class primitive_iterator_t
6113 void set_begin() noexcept
6119 void set_end() noexcept
6125 constexpr
bool is_begin()
const noexcept
6127 return (m_it == begin_value);
6131 constexpr
bool is_end()
const noexcept
6133 return (m_it == end_value);
6153 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6163 struct internal_iterator
6166 typename object_t::iterator object_iterator;
6168 typename array_t::iterator array_iterator;
6170 primitive_iterator_t primitive_iterator;
6173 internal_iterator() noexcept
6174 : object_iterator(), array_iterator(), primitive_iterator()
6179 template<
typename IteratorType>
6180 class iteration_proxy
6184 class iteration_proxy_internal
6188 IteratorType anchor;
6190 size_t array_index = 0;
6193 explicit iteration_proxy_internal(IteratorType it) noexcept
6198 iteration_proxy_internal& operator*()
6204 iteration_proxy_internal& operator++()
6213 bool operator!= (
const iteration_proxy_internal& o)
const 6215 return anchor != o.anchor;
6221 assert(anchor.m_object !=
nullptr);
6223 switch (anchor.m_object->type())
6226 case value_t::array:
6228 return std::to_string(array_index);
6232 case value_t::object:
6234 return anchor.key();
6246 typename IteratorType::reference value()
const 6248 return anchor.value();
6253 typename IteratorType::reference container;
6257 explicit iteration_proxy(
typename IteratorType::reference cont)
6262 iteration_proxy_internal begin() noexcept
6264 return iteration_proxy_internal(container.begin());
6268 iteration_proxy_internal end() noexcept
6270 return iteration_proxy_internal(container.end());
6288 class const_iterator :
public std::iterator<std::random_access_iterator_tag, const basic_json>
6291 friend class basic_json;
6312 assert(m_object !=
nullptr);
6314 switch (m_object->m_type)
6318 m_it.object_iterator =
typename object_t::iterator();
6324 m_it.array_iterator =
typename array_t::iterator();
6330 m_it.primitive_iterator = primitive_iterator_t();
6338 : m_object(other.m_object)
6340 assert(m_object !=
nullptr);
6342 switch (m_object->m_type)
6346 m_it.object_iterator = other.m_it.object_iterator;
6352 m_it.array_iterator = other.m_it.array_iterator;
6358 m_it.primitive_iterator = other.m_it.primitive_iterator;
6366 : m_object(other.m_object), m_it(other.m_it)
6371 std::is_nothrow_move_constructible<pointer>::value and
6372 std::is_nothrow_move_assignable<pointer>::value and
6373 std::is_nothrow_move_constructible<internal_iterator>::value and
6374 std::is_nothrow_move_assignable<internal_iterator>::value
6377 std::swap(m_object, other.m_object);
6378 std::swap(m_it, other.m_it);
6384 void set_begin() noexcept
6386 assert(m_object !=
nullptr);
6388 switch (m_object->m_type)
6392 assert(m_object->m_value.object !=
nullptr);
6393 m_it.object_iterator = m_object->m_value.object->begin();
6399 assert(m_object->m_value.array !=
nullptr);
6400 m_it.array_iterator = m_object->m_value.array->begin();
6407 m_it.primitive_iterator.set_end();
6413 m_it.primitive_iterator.set_begin();
6420 void set_end() noexcept
6422 assert(m_object !=
nullptr);
6424 switch (m_object->m_type)
6428 assert(m_object->m_value.object !=
nullptr);
6429 m_it.object_iterator = m_object->m_value.object->end();
6435 assert(m_object->m_value.array !=
nullptr);
6436 m_it.array_iterator = m_object->m_value.array->end();
6442 m_it.primitive_iterator.set_end();
6452 assert(m_object !=
nullptr);
6454 switch (m_object->m_type)
6458 assert(m_object->m_value.object);
6459 assert(m_it.object_iterator != m_object->m_value.object->end());
6460 return m_it.object_iterator->second;
6465 assert(m_object->m_value.array);
6466 assert(m_it.array_iterator != m_object->m_value.array->end());
6467 return *m_it.array_iterator;
6472 throw std::out_of_range(
"cannot get value");
6477 if (m_it.primitive_iterator.is_begin())
6483 throw std::out_of_range(
"cannot get value");
6492 assert(m_object !=
nullptr);
6494 switch (m_object->m_type)
6498 assert(m_object->m_value.object);
6499 assert(m_it.object_iterator != m_object->m_value.object->end());
6500 return &(m_it.object_iterator->second);
6505 assert(m_object->m_value.array);
6506 assert(m_it.array_iterator != m_object->m_value.array->end());
6507 return &*m_it.array_iterator;
6512 if (m_it.primitive_iterator.is_begin())
6518 throw std::out_of_range(
"cannot get value");
6527 auto result = *
this;
6535 assert(m_object !=
nullptr);
6537 switch (m_object->m_type)
6541 ++m_it.object_iterator;
6547 ++m_it.array_iterator;
6553 ++m_it.primitive_iterator;
6564 auto result = *
this;
6572 assert(m_object !=
nullptr);
6574 switch (m_object->m_type)
6578 --m_it.object_iterator;
6584 --m_it.array_iterator;
6590 --m_it.primitive_iterator;
6602 if (m_object != other.m_object)
6604 throw std::domain_error(
"cannot compare iterators of different containers");
6607 assert(m_object !=
nullptr);
6609 switch (m_object->m_type)
6613 return (m_it.object_iterator == other.m_it.object_iterator);
6618 return (m_it.array_iterator == other.m_it.array_iterator);
6623 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6631 return not operator==(other);
6638 if (m_object != other.m_object)
6640 throw std::domain_error(
"cannot compare iterators of different containers");
6643 assert(m_object !=
nullptr);
6645 switch (m_object->m_type)
6649 throw std::domain_error(
"cannot compare order of object iterators");
6654 return (m_it.array_iterator < other.m_it.array_iterator);
6659 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6667 return not other.operator < (*this);
6673 return not operator<=(other);
6679 return not operator<(other);
6685 assert(m_object !=
nullptr);
6687 switch (m_object->m_type)
6691 throw std::domain_error(
"cannot use offsets with object iterators");
6696 m_it.array_iterator += i;
6702 m_it.primitive_iterator += i;
6713 return operator+=(-i);
6719 auto result = *
this;
6727 auto result = *
this;
6735 assert(m_object !=
nullptr);
6737 switch (m_object->m_type)
6741 throw std::domain_error(
"cannot use offsets with object iterators");
6746 return m_it.array_iterator - other.m_it.array_iterator;
6751 return m_it.primitive_iterator - other.m_it.primitive_iterator;
6759 assert(m_object !=
nullptr);
6761 switch (m_object->m_type)
6765 throw std::domain_error(
"cannot use operator[] for object iterators");
6770 return *(m_it.array_iterator + n);
6775 throw std::out_of_range(
"cannot get value");
6780 if (m_it.primitive_iterator == -n)
6786 throw std::out_of_range(
"cannot get value");
6793 typename object_t::key_type
key()
const 6795 assert(m_object !=
nullptr);
6797 if (m_object->is_object())
6799 return m_it.object_iterator->first;
6803 throw std::domain_error(
"cannot use key() for non-object iterators");
6817 internal_iterator m_it = internal_iterator();
6854 std::is_nothrow_move_constructible<pointer>::value and
6855 std::is_nothrow_move_assignable<pointer>::value and
6856 std::is_nothrow_move_constructible<internal_iterator>::value and
6857 std::is_nothrow_move_assignable<internal_iterator>::value
6860 base_iterator::operator=(other);
6867 return const_cast<reference>(base_iterator::operator*());
6873 return const_cast<pointer>(base_iterator::operator->());
6880 base_iterator::operator++();
6887 base_iterator::operator++();
6895 base_iterator::operator--();
6902 base_iterator::operator--();
6909 base_iterator::operator+=(i);
6916 base_iterator::operator-=(i);
6923 auto result = *
this;
6931 auto result = *
this;
6939 return base_iterator::operator-(other);
6945 return const_cast<reference>(base_iterator::operator[](n));
6951 return const_cast<reference>(base_iterator::value());
6972 template<
typename Base>
6994 return base_iterator::operator++(1);
7000 base_iterator::operator++();
7007 return base_iterator::operator--(1);
7013 base_iterator::operator--();
7020 base_iterator::operator+=(i);
7027 auto result = *
this;
7035 auto result = *
this;
7043 return this->base() - other.base();
7049 return *(this->operator+(n));
7053 typename object_t::key_type
key()
const 7055 auto it = --this->base();
7062 auto it = --this->base();
7063 return it.operator * ();
7084 enum class token_type
7103 using lexer_char_t =
unsigned char;
7106 explicit lexer(
const string_t& s) noexcept
7107 : m_stream(
nullptr), m_buffer(s)
7109 m_content =
reinterpret_cast<const lexer_char_t*
>(s.c_str());
7110 assert(m_content !=
nullptr);
7111 m_start = m_cursor = m_content;
7112 m_limit = m_content + s.size();
7116 explicit lexer(std::istream* s) noexcept
7117 : m_stream(s), m_buffer()
7119 assert(m_stream !=
nullptr);
7120 getline(*m_stream, m_buffer);
7121 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
7122 assert(m_content !=
nullptr);
7123 m_start = m_cursor = m_content;
7124 m_limit = m_content + m_buffer.size();
7131 lexer(
const lexer&) =
delete;
7132 lexer operator=(
const lexer&) =
delete;
7149 static string_t to_unicode(
const std::size_t codepoint1,
7150 const std::size_t codepoint2 = 0)
7153 std::size_t codepoint = codepoint1;
7156 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7159 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7173 throw std::invalid_argument(
"missing or wrong low surrogate");
7179 if (codepoint < 0x80)
7182 result.append(1, static_cast<typename string_t::value_type>(codepoint));
7184 else if (codepoint <= 0x7ff)
7187 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7188 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7190 else if (codepoint <= 0xffff)
7193 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7194 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7195 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7197 else if (codepoint <= 0x10ffff)
7200 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7201 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7202 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7203 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7207 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
7214 static std::string token_type_name(token_type t)
7218 case token_type::uninitialized:
7219 return "<uninitialized>";
7220 case token_type::literal_true:
7221 return "true literal";
7222 case token_type::literal_false:
7223 return "false literal";
7224 case token_type::literal_null:
7225 return "null literal";
7226 case token_type::value_string:
7227 return "string literal";
7228 case token_type::value_number:
7229 return "number literal";
7230 case token_type::begin_array:
7232 case token_type::begin_object:
7234 case token_type::end_array:
7236 case token_type::end_object:
7238 case token_type::name_separator:
7240 case token_type::value_separator:
7242 case token_type::parse_error:
7243 return "<parse error>";
7244 case token_type::end_of_input:
7245 return "end of input";
7249 return "unknown token";
7264 token_type scan() noexcept
7271 assert(m_start !=
nullptr);
7276 unsigned int yyaccept = 0;
7277 static const unsigned char yybm[] =
7279 0, 0, 0, 0, 0, 0, 0, 0,
7280 0, 32, 32, 0, 0, 32, 0, 0,
7281 128, 128, 128, 128, 128, 128, 128, 128,
7282 128, 128, 128, 128, 128, 128, 128, 128,
7283 160, 128, 0, 128, 128, 128, 128, 128,
7284 128, 128, 128, 128, 128, 128, 128, 128,
7285 192, 192, 192, 192, 192, 192, 192, 192,
7286 192, 192, 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, 0, 128, 128, 128,
7291 128, 128, 128, 128, 128, 128, 128, 128,
7292 128, 128, 128, 128, 128, 128, 128, 128,
7293 128, 128, 128, 128, 128, 128, 128, 128,
7294 128, 128, 128, 128, 128, 128, 128, 128,
7295 128, 128, 128, 128, 128, 128, 128, 128,
7296 128, 128, 128, 128, 128, 128, 128, 128,
7297 128, 128, 128, 128, 128, 128, 128, 128,
7298 128, 128, 128, 128, 128, 128, 128, 128,
7299 128, 128, 128, 128, 128, 128, 128, 128,
7300 128, 128, 128, 128, 128, 128, 128, 128,
7301 128, 128, 128, 128, 128, 128, 128, 128,
7302 128, 128, 128, 128, 128, 128, 128, 128,
7303 128, 128, 128, 128, 128, 128, 128, 128,
7304 128, 128, 128, 128, 128, 128, 128, 128,
7305 128, 128, 128, 128, 128, 128, 128, 128,
7306 128, 128, 128, 128, 128, 128, 128, 128,
7307 128, 128, 128, 128, 128, 128, 128, 128,
7308 128, 128, 128, 128, 128, 128, 128, 128,
7309 128, 128, 128, 128, 128, 128, 128, 128,
7310 128, 128, 128, 128, 128, 128, 128, 128,
7312 if ((m_limit - m_cursor) < 5)
7317 if (yybm[0 + yych] & 32)
7319 goto basic_json_parser_6;
7329 goto basic_json_parser_2;
7333 goto basic_json_parser_4;
7335 goto basic_json_parser_9;
7341 goto basic_json_parser_4;
7345 goto basic_json_parser_10;
7347 goto basic_json_parser_12;
7356 goto basic_json_parser_4;
7360 goto basic_json_parser_13;
7362 goto basic_json_parser_15;
7368 goto basic_json_parser_17;
7372 goto basic_json_parser_19;
7374 goto basic_json_parser_4;
7386 goto basic_json_parser_21;
7390 goto basic_json_parser_4;
7392 goto basic_json_parser_23;
7398 goto basic_json_parser_24;
7402 goto basic_json_parser_4;
7404 goto basic_json_parser_25;
7413 goto basic_json_parser_26;
7415 goto basic_json_parser_4;
7421 goto basic_json_parser_28;
7425 goto basic_json_parser_30;
7427 goto basic_json_parser_4;
7431 basic_json_parser_2:
7434 return token_type::end_of_input;
7436 basic_json_parser_4:
7438 basic_json_parser_5:
7440 return token_type::parse_error;
7442 basic_json_parser_6:
7444 if (m_limit <= m_cursor)
7449 if (yybm[0 + yych] & 32)
7451 goto basic_json_parser_6;
7456 basic_json_parser_9:
7458 yych = *(m_marker = ++m_cursor);
7461 goto basic_json_parser_5;
7463 goto basic_json_parser_32;
7464 basic_json_parser_10:
7467 return token_type::value_separator;
7469 basic_json_parser_12:
7473 goto basic_json_parser_5;
7477 goto basic_json_parser_13;
7481 goto basic_json_parser_15;
7483 goto basic_json_parser_5;
7484 basic_json_parser_13:
7486 yych = *(m_marker = ++m_cursor);
7491 goto basic_json_parser_37;
7498 goto basic_json_parser_38;
7502 goto basic_json_parser_38;
7505 basic_json_parser_14:
7507 return token_type::value_number;
7509 basic_json_parser_15:
7511 m_marker = ++m_cursor;
7512 if ((m_limit - m_cursor) < 3)
7517 if (yybm[0 + yych] & 64)
7519 goto basic_json_parser_15;
7525 goto basic_json_parser_37;
7527 goto basic_json_parser_14;
7533 goto basic_json_parser_38;
7537 goto basic_json_parser_38;
7539 goto basic_json_parser_14;
7541 basic_json_parser_17:
7544 return token_type::name_separator;
7546 basic_json_parser_19:
7549 return token_type::begin_array;
7551 basic_json_parser_21:
7554 return token_type::end_array;
7556 basic_json_parser_23:
7558 yych = *(m_marker = ++m_cursor);
7561 goto basic_json_parser_39;
7563 goto basic_json_parser_5;
7564 basic_json_parser_24:
7566 yych = *(m_marker = ++m_cursor);
7569 goto basic_json_parser_40;
7571 goto basic_json_parser_5;
7572 basic_json_parser_25:
7574 yych = *(m_marker = ++m_cursor);
7577 goto basic_json_parser_41;
7579 goto basic_json_parser_5;
7580 basic_json_parser_26:
7583 return token_type::begin_object;
7585 basic_json_parser_28:
7588 return token_type::end_object;
7590 basic_json_parser_30:
7592 yych = *(m_marker = ++m_cursor);
7595 goto basic_json_parser_42;
7597 goto basic_json_parser_5;
7598 basic_json_parser_31:
7600 if (m_limit <= m_cursor)
7605 basic_json_parser_32:
7606 if (yybm[0 + yych] & 128)
7608 goto basic_json_parser_31;
7612 goto basic_json_parser_33;
7616 goto basic_json_parser_34;
7618 goto basic_json_parser_36;
7619 basic_json_parser_33:
7620 m_cursor = m_marker;
7623 goto basic_json_parser_5;
7627 goto basic_json_parser_14;
7629 basic_json_parser_34:
7632 return token_type::value_string;
7634 basic_json_parser_36:
7636 if (m_limit <= m_cursor)
7647 goto basic_json_parser_31;
7651 goto basic_json_parser_33;
7653 goto basic_json_parser_31;
7661 goto basic_json_parser_33;
7663 goto basic_json_parser_31;
7669 goto basic_json_parser_31;
7671 goto basic_json_parser_33;
7681 goto basic_json_parser_31;
7685 goto basic_json_parser_31;
7687 goto basic_json_parser_33;
7695 goto basic_json_parser_31;
7697 goto basic_json_parser_33;
7703 goto basic_json_parser_31;
7707 goto basic_json_parser_43;
7709 goto basic_json_parser_33;
7713 basic_json_parser_37:
7717 goto basic_json_parser_33;
7721 goto basic_json_parser_44;
7723 goto basic_json_parser_33;
7724 basic_json_parser_38:
7730 goto basic_json_parser_46;
7732 goto basic_json_parser_33;
7738 goto basic_json_parser_46;
7742 goto basic_json_parser_33;
7746 goto basic_json_parser_47;
7748 goto basic_json_parser_33;
7750 basic_json_parser_39:
7754 goto basic_json_parser_49;
7756 goto basic_json_parser_33;
7757 basic_json_parser_40:
7761 goto basic_json_parser_50;
7763 goto basic_json_parser_33;
7764 basic_json_parser_41:
7768 goto basic_json_parser_51;
7770 goto basic_json_parser_33;
7771 basic_json_parser_42:
7775 goto basic_json_parser_52;
7777 goto basic_json_parser_33;
7778 basic_json_parser_43:
7780 if (m_limit <= m_cursor)
7789 goto basic_json_parser_33;
7793 goto basic_json_parser_54;
7795 goto basic_json_parser_33;
7801 goto basic_json_parser_54;
7805 goto basic_json_parser_33;
7809 goto basic_json_parser_54;
7811 goto basic_json_parser_33;
7813 basic_json_parser_44:
7815 m_marker = ++m_cursor;
7816 if ((m_limit - m_cursor) < 3)
7825 goto basic_json_parser_14;
7829 goto basic_json_parser_44;
7831 goto basic_json_parser_14;
7837 goto basic_json_parser_38;
7841 goto basic_json_parser_38;
7843 goto basic_json_parser_14;
7845 basic_json_parser_46:
7849 goto basic_json_parser_33;
7853 goto basic_json_parser_33;
7855 basic_json_parser_47:
7857 if (m_limit <= m_cursor)
7864 goto basic_json_parser_14;
7868 goto basic_json_parser_47;
7870 goto basic_json_parser_14;
7871 basic_json_parser_49:
7875 goto basic_json_parser_55;
7877 goto basic_json_parser_33;
7878 basic_json_parser_50:
7882 goto basic_json_parser_56;
7884 goto basic_json_parser_33;
7885 basic_json_parser_51:
7889 goto basic_json_parser_58;
7891 goto basic_json_parser_33;
7892 basic_json_parser_52:
7897 basic_json_parser_54:
7899 if (m_limit <= m_cursor)
7908 goto basic_json_parser_33;
7912 goto basic_json_parser_60;
7914 goto basic_json_parser_33;
7920 goto basic_json_parser_60;
7924 goto basic_json_parser_33;
7928 goto basic_json_parser_60;
7930 goto basic_json_parser_33;
7932 basic_json_parser_55:
7936 goto basic_json_parser_61;
7938 goto basic_json_parser_33;
7939 basic_json_parser_56:
7942 return token_type::literal_null;
7944 basic_json_parser_58:
7947 return token_type::literal_true;
7949 basic_json_parser_60:
7951 if (m_limit <= m_cursor)
7960 goto basic_json_parser_33;
7964 goto basic_json_parser_63;
7966 goto basic_json_parser_33;
7972 goto basic_json_parser_63;
7976 goto basic_json_parser_33;
7980 goto basic_json_parser_63;
7982 goto basic_json_parser_33;
7984 basic_json_parser_61:
7987 return token_type::literal_false;
7989 basic_json_parser_63:
7991 if (m_limit <= m_cursor)
8000 goto basic_json_parser_33;
8004 goto basic_json_parser_31;
8006 goto basic_json_parser_33;
8012 goto basic_json_parser_31;
8016 goto basic_json_parser_33;
8020 goto basic_json_parser_31;
8022 goto basic_json_parser_33;
8029 void yyfill() noexcept
8031 if (m_stream ==
nullptr or not * m_stream)
8036 const auto offset_start = m_start - m_content;
8037 const auto offset_marker = m_marker - m_start;
8038 const auto offset_cursor = m_cursor - m_start;
8040 m_buffer.erase(0, static_cast<size_t>(offset_start));
8042 assert(m_stream !=
nullptr);
8043 std::getline(*m_stream, line);
8044 m_buffer +=
"\n" + line;
8046 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
8047 assert(m_content !=
nullptr);
8048 m_start = m_content;
8049 m_marker = m_start + offset_marker;
8050 m_cursor = m_start + offset_cursor;
8051 m_limit = m_start + m_buffer.size() - 1;
8057 assert(m_start !=
nullptr);
8058 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8059 static_cast<size_t>(m_cursor - m_start));
8086 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8089 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8145 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8146 4).c_str(),
nullptr, 16);
8149 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8152 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
8154 throw std::invalid_argument(
"missing low surrogate");
8158 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8159 (i + 7), 4).c_str(),
nullptr, 16);
8160 result += to_unicode(codepoint, codepoint2);
8167 result += to_unicode(codepoint);
8179 result.append(1, static_cast<typename string_t::value_type>(*i));
8206 long double str_to_float_t(
long double* ,
char** endptr)
const 8208 return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8226 double str_to_float_t(
double* ,
char** endptr)
const 8228 return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8246 float str_to_float_t(
float* ,
char** endptr)
const 8248 return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8263 template <
typename T_A,
typename T_B>
8264 static bool attempt_cast(T_A source, T_B& dest)
8266 dest =
static_cast<T_B
>(source);
8267 return (source == static_cast<T_A>(dest));
8308 void get_number(basic_json& result)
const 8310 typename string_t::value_type* endptr;
8311 assert(m_start !=
nullptr);
8316 if (*reinterpret_cast<typename string_t::const_pointer>(m_start) !=
'-')
8320 if (attempt_cast(std::strtoull(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr,
8321 10), result.m_value.number_unsigned))
8323 result.m_type = value_t::number_unsigned;
8328 result.m_type = value_t::number_float;
8335 if (attempt_cast(std::strtoll(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr,
8336 10), result.m_value.number_integer))
8338 result.m_type = value_t::number_integer;
8343 result.m_type = value_t::number_float;
8349 if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor || errno == ERANGE)
8351 result.m_type = value_t::number_float;
8354 if (result.m_type == value_t::number_float)
8361 result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(
nullptr), &endptr);
8364 if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor)
8366 throw std::invalid_argument(std::string(
"parse error - ") + get_token() +
" is not a number");
8373 std::istream* m_stream =
nullptr;
8377 const lexer_char_t* m_content =
nullptr;
8379 const lexer_char_t* m_start =
nullptr;
8381 const lexer_char_t* m_marker =
nullptr;
8383 const lexer_char_t* m_cursor =
nullptr;
8385 const lexer_char_t* m_limit =
nullptr;
8398 : callback(cb), m_lexer(s)
8406 : callback(cb), m_lexer(&_is)
8415 basic_json result = parse_internal(
true);
8417 expect(lexer::token_type::end_of_input);
8426 basic_json parse_internal(
bool keep)
8428 auto result = basic_json(value_t::discarded);
8432 case lexer::token_type::begin_object:
8434 if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
8437 result.m_type = value_t::object;
8438 result.m_value = json_value(value_t::object);
8445 if (last_token == lexer::token_type::end_object)
8448 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8450 result = basic_json(value_t::discarded);
8456 unexpect(lexer::token_type::value_separator);
8462 if (last_token == lexer::token_type::value_separator)
8468 expect(lexer::token_type::value_string);
8469 const auto key = m_lexer.get_string();
8471 bool keep_tag =
false;
8477 keep_tag = callback(depth, parse_event_t::key, k);
8487 expect(lexer::token_type::name_separator);
8491 auto value = parse_internal(keep);
8492 if (keep and keep_tag and not value.is_discarded())
8494 result[key] = std::move(value);
8497 while (last_token == lexer::token_type::value_separator);
8500 expect(lexer::token_type::end_object);
8502 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8504 result = basic_json(value_t::discarded);
8510 case lexer::token_type::begin_array:
8512 if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
8515 result.m_type = value_t::array;
8516 result.m_value = json_value(value_t::array);
8523 if (last_token == lexer::token_type::end_array)
8526 if (callback and not callback(--depth, parse_event_t::array_end, result))
8528 result = basic_json(value_t::discarded);
8534 unexpect(lexer::token_type::value_separator);
8540 if (last_token == lexer::token_type::value_separator)
8546 auto value = parse_internal(keep);
8547 if (keep and not value.is_discarded())
8549 result.push_back(std::move(value));
8552 while (last_token == lexer::token_type::value_separator);
8555 expect(lexer::token_type::end_array);
8557 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8559 result = basic_json(value_t::discarded);
8565 case lexer::token_type::literal_null:
8568 result.m_type = value_t::null;
8572 case lexer::token_type::value_string:
8574 const auto s = m_lexer.get_string();
8576 result = basic_json(s);
8580 case lexer::token_type::literal_true:
8583 result.m_type = value_t::boolean;
8584 result.m_value =
true;
8588 case lexer::token_type::literal_false:
8591 result.m_type = value_t::boolean;
8592 result.m_value =
false;
8596 case lexer::token_type::value_number:
8598 m_lexer.get_number(result);
8606 unexpect(last_token);
8610 if (keep and callback and not callback(depth, parse_event_t::value, result))
8612 result = basic_json(value_t::discarded);
8618 typename lexer::token_type get_token() noexcept
8620 last_token = m_lexer.scan();
8624 void expect(
typename lexer::token_type t)
const 8626 if (t != last_token)
8628 std::string error_msg =
"parse error - unexpected ";
8629 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token() +
"'") :
8630 lexer::token_type_name(last_token));
8631 error_msg +=
"; expected " + lexer::token_type_name(t);
8632 throw std::invalid_argument(error_msg);
8636 void unexpect(
typename lexer::token_type t)
const 8638 if (t == last_token)
8640 std::string error_msg =
"parse error - unexpected ";
8641 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token() +
"'") :
8642 lexer::token_type_name(last_token));
8643 throw std::invalid_argument(error_msg);
8653 typename lexer::token_type last_token = lexer::token_type::uninitialized;
8691 is_nothrow_move_constructible<nlohmann::json>::value and
8692 is_nothrow_move_assignable<nlohmann::json>::value
8710 const auto& h = hash<nlohmann::json::string_t>();
8728 inline nlohmann::json operator "" _json(
const char* s, std::size_t)
8734 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 8735 #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.