38 #ifndef NLOHMANN_JSON_HPP
39 #define NLOHMANN_JSON_HPP
47 #include <initializer_list>
56 #include <type_traits>
63 #include <sys/types.h>
70 using ssize_t = SSIZE_T;
93 struct has_mapped_type
96 template<
typename C>
static char test(
typename C::mapped_type*);
97 template<
typename C>
static int test(...);
99 enum { value =
sizeof(test<T>(0)) ==
sizeof(char) };
104 static bool approx(
const T a,
const T b)
106 return not (a > b or a < b);
179 template<
typename U,
typename V,
typename... Args>
class ObjectType = std::map,
180 template<
typename U,
typename... Args>
class ArrayType = std::vector,
181 class StringType = std::string,
182 class BooleanType = bool,
183 class NumberIntegerType = int64_t,
184 class NumberFloatType = double,
185 template<
typename U>
class AllocatorType = std::allocator
227 using pointer =
typename std::allocator_traits<allocator_type>::pointer;
229 using const_pointer =
typename std::allocator_traits<allocator_type>::const_pointer;
336 using object_t = ObjectType<StringType,
338 std::less<StringType>,
339 AllocatorType<std::pair<
const StringType,
386 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
626 template<
typename T,
typename... Args>
627 static T* create(Args&& ... args)
629 AllocatorType<T> alloc;
630 auto deleter = [&](T *
object)
632 alloc.deallocate(
object, 1);
634 std::unique_ptr<T, decltype(deleter)>
object(alloc.allocate(1), deleter);
635 alloc.construct(
object.
get(), std::forward<Args>(args)...);
636 return object.release();
666 json_value() noexcept = default;
668 json_value(
boolean_t v) noexcept :
boolean(v) {}
680 object = create<object_t>();
686 array = create<array_t>();
692 string = create<string_t>(
"");
724 string = create<string_t>(
value);
730 object = create<object_t>(
value);
736 array = create<array_t>(
value);
819 using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
867 : m_type(value_type), m_value(value_type)
910 basic_json(
std::nullptr_t) noexcept
934 : m_type(
value_t::object), m_value(val)
960 template <
class CompatibleObjectType,
typename
962 std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
963 std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value,
int>
::type
970 m_value.object = create<object_t>(
begin(val),
end(val));
993 : m_type(
value_t::array), m_value(val)
1019 template <
class CompatibleArrayType,
typename
1021 not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1022 not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1023 not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1024 not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1025 not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1026 not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1027 std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value,
int>::type
1034 m_value.array = create<array_t>(
begin(val),
end(val));
1059 : m_type(
value_t::string), m_value(val)
1109 template <
class CompatibleStringType,
typename
1111 std::is_constructible<string_t, CompatibleStringType>::value,
int>::type
1132 : m_type(
value_t::boolean), m_value(val)
1160 template<
typename T,
1161 typename std::enable_if<
1162 not (std::is_same<T, int>::value)
1166 : m_type(
value_t::number_integer), m_value(val)
1195 : m_type(
value_t::number_integer),
1224 template<
typename CompatibleNumberIntegerType,
typename
1226 std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1227 std::numeric_limits<CompatibleNumberIntegerType>::is_integer, CompatibleNumberIntegerType>::type
1231 m_value(static_cast<number_integer_t>(val))
1259 : m_type(
value_t::number_float), m_value(val)
1262 if (not std::isfinite(val))
1265 m_value = json_value();
1299 template<
typename CompatibleNumberFloatType,
typename =
typename
1301 std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1302 std::is_floating_point<CompatibleNumberFloatType>::value>::type
1377 bool type_deduction =
true,
1381 bool is_an_object =
true;
1385 for (
const auto& element : init)
1387 if (not element.is_array() or element.size() != 2
1388 or not element[0].is_string())
1392 is_an_object =
false;
1398 if (not type_deduction)
1403 is_an_object =
false;
1409 throw std::domain_error(
"cannot create object from initializer list");
1419 for (
auto& element : init)
1421 m_value.object->emplace(std::move(*(element[0].m_value.string)), std::move(element[1]));
1428 m_value.array = create<array_t>(std::move(init));
1466 static basic_json
array(std::initializer_list<basic_json> init =
1467 std::initializer_list<basic_json>())
1506 static basic_json
object(std::initializer_list<basic_json> init =
1507 std::initializer_list<basic_json>())
1533 m_value.array = create<array_t>(cnt, val);
1568 template <
class InputIT,
typename
1570 std::is_same<InputIT, typename basic_json_t::iterator>::value or
1571 std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1574 basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1577 if (first.m_object != last.m_object)
1579 throw std::domain_error(
"iterators are not compatible");
1590 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1592 throw std::out_of_range(
"iterators out of range");
1607 m_value.number_integer = first.m_object->m_value.number_integer;
1613 m_value.number_float = first.m_object->m_value.number_float;
1619 m_value.boolean = first.m_object->m_value.boolean;
1625 m_value = *first.m_object->m_value.string;
1631 m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1637 m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1643 throw std::domain_error(
"cannot use construct with iterators from " + first.m_object->type_name());
1673 : m_type(other.m_type)
1679 m_value = *other.m_value.object;
1685 m_value = *other.m_value.array;
1691 m_value = *other.m_value.string;
1697 m_value = other.m_value.boolean;
1703 m_value = other.m_value.number_integer;
1709 m_value = other.m_value.number_float;
1739 : m_type(
std::move(other.m_type)),
1740 m_value(
std::move(other.m_value))
1769 std::is_nothrow_move_constructible<value_t>::value and
1770 std::is_nothrow_move_assignable<value_t>::value and
1771 std::is_nothrow_move_constructible<json_value>::value and
1772 std::is_nothrow_move_assignable<json_value>::value
1776 swap(m_type, other.m_type);
1777 swap(m_value, other.m_value);
1800 AllocatorType<object_t> alloc;
1801 alloc.destroy(m_value.object);
1802 alloc.deallocate(m_value.object, 1);
1808 AllocatorType<array_t> alloc;
1809 alloc.destroy(m_value.array);
1810 alloc.deallocate(m_value.array, 1);
1816 AllocatorType<string_t> alloc;
1817 alloc.destroy(m_value.string);
1818 alloc.deallocate(m_value.string, 1);
1865 std::stringstream ss;
1869 dump(ss,
true, static_cast<unsigned int>(indent));
2157 template <
class T,
typename
2159 std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2160 std::is_convertible<basic_json_t, typename T::mapped_type>::value
2162 T get_impl(T*)
const
2166 return T(m_value.object->begin(), m_value.object->end());
2170 throw std::domain_error(
"type must be object, but is " + type_name());
2179 return *(m_value.object);
2183 throw std::domain_error(
"type must be object, but is " + type_name());
2188 template <
class T,
typename
2190 std::is_convertible<basic_json_t, typename T::value_type>::value and
2191 not std::is_same<basic_json_t, typename T::value_type>::value and
2192 not std::is_arithmetic<T>::value and
2193 not std::is_convertible<std::string, T>::value and
2194 not has_mapped_type<T>::value
2196 T get_impl(T*)
const
2201 std::transform(m_value.array->begin(), m_value.array->end(),
2202 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2204 return i.get<
typename T::value_type>();
2210 throw std::domain_error(
"type must be array, but is " + type_name());
2215 template <
class T,
typename
2217 std::is_convertible<basic_json_t, T>::value and
2218 not std::is_same<basic_json_t, T>::value
2220 std::vector<T> get_impl(std::vector<T>*)
const
2224 std::vector<T> to_vector;
2225 to_vector.reserve(m_value.array->size());
2226 std::transform(m_value.array->begin(), m_value.array->end(),
2227 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2235 throw std::domain_error(
"type must be array, but is " + type_name());
2240 template <
class T,
typename
2242 std::is_same<basic_json, typename T::value_type>::value and
2243 not has_mapped_type<T>::value
2245 T get_impl(T*)
const
2249 return T(m_value.array->begin(), m_value.array->end());
2253 throw std::domain_error(
"type must be array, but is " + type_name());
2262 return *(m_value.array);
2266 throw std::domain_error(
"type must be array, but is " + type_name());
2271 template <
typename T,
typename
2273 std::is_convertible<string_t, T>::value
2275 T get_impl(T*)
const
2279 return *m_value.string;
2283 throw std::domain_error(
"type must be string, but is " + type_name());
2288 template<
typename T,
typename
2290 std::is_arithmetic<T>::value
2292 T get_impl(T*)
const
2298 return static_cast<T
>(m_value.number_integer);
2303 return static_cast<T
>(m_value.number_float);
2308 throw std::domain_error(
"type must be number, but is " + type_name());
2318 return m_value.boolean;
2322 throw std::domain_error(
"type must be boolean, but is " + type_name());
2329 return is_object() ? m_value.object :
nullptr;
2335 return is_object() ? m_value.object :
nullptr;
2341 return is_array() ? m_value.array :
nullptr;
2347 return is_array() ? m_value.array :
nullptr;
2353 return is_string() ? m_value.string :
nullptr;
2359 return is_string() ? m_value.string :
nullptr;
2365 return is_boolean() ? &m_value.boolean :
nullptr;
2371 return is_boolean() ? &m_value.boolean :
nullptr;
2436 template<
typename ValueType,
typename
2438 not std::is_pointer<ValueType>::value
2440 ValueType
get()
const
2442 return get_impl(static_cast<ValueType*>(
nullptr));
2471 template<
typename PointerType,
typename
2473 std::is_pointer<PointerType>::value
2475 PointerType
get() noexcept
2478 return get_ptr<PointerType>();
2485 template<
typename PointerType,
typename
2487 std::is_pointer<PointerType>::value
2489 const PointerType
get()
const noexcept
2492 return get_ptr<PointerType>();
2520 template<
typename PointerType,
typename
2522 std::is_pointer<PointerType>::value
2527 return get_impl_ptr(static_cast<PointerType>(
nullptr));
2534 template<
typename PointerType,
typename
2536 std::is_pointer<PointerType>::value
2537 and std::is_const<typename std::remove_pointer<PointerType>::type>
::value
2542 return get_impl_ptr(static_cast<const PointerType>(
nullptr));
2573 template<
typename ValueType,
typename
2575 not std::is_pointer<ValueType>::value
2576 and not std::is_same<ValueType, typename string_t::value_type>::value
2577 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>
::value
2579 operator ValueType()
const
2582 return get<ValueType>();
2624 return m_value.array->at(idx);
2626 catch (std::out_of_range& e)
2629 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
2634 throw std::domain_error(
"cannot use at() with " + type_name());
2667 return m_value.array->at(idx);
2669 catch (std::out_of_range& e)
2672 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
2677 throw std::domain_error(
"cannot use at() with " + type_name());
2714 return m_value.object->at(key);
2716 catch (std::out_of_range& e)
2719 throw std::out_of_range(
"key '" + key +
"' not found");
2724 throw std::domain_error(
"cannot use at() with " + type_name());
2761 return m_value.object->at(key);
2763 catch (std::out_of_range& e)
2766 throw std::out_of_range(
"key '" + key +
"' not found");
2771 throw std::domain_error(
"cannot use at() with " + type_name());
2805 m_value.array = create<array_t>();
2811 for (
size_t i = m_value.array->size(); i <= idx; ++i)
2816 return m_value.array->operator[](idx);
2820 throw std::domain_error(
"cannot use operator[] with " + type_name());
2847 return m_value.array->operator[](idx);
2851 throw std::domain_error(
"cannot use operator[] with " + type_name());
2887 m_value.object = create<object_t>();
2893 return m_value.object->operator[](key);
2897 throw std::domain_error(
"cannot use operator[] with " + type_name());
2932 return m_value.object->find(key)->second;
2936 throw std::domain_error(
"cannot use operator[] with " + type_name());
2968 template<
typename T, std::
size_t n>
2981 return m_value.object->operator[](key);
2985 throw std::domain_error(
"cannot use operator[] with " + type_name());
3017 template<
typename T, std::
size_t n>
3023 return m_value.object->find(key)->second;
3027 throw std::domain_error(
"cannot use operator[] with " + type_name());
3078 template <
class ValueType,
typename
3080 std::is_convertible<basic_json_t, ValueType>::value
3082 ValueType
value(
const typename object_t::key_type& key, ValueType default_value)
const
3088 const auto it =
find(key);
3095 return default_value;
3100 throw std::domain_error(
"cannot use value() with " + type_name());
3108 string_t value(
const typename object_t::key_type& key,
const char* default_value)
const
3226 template <
class InteratorType,
typename
3228 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3229 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3235 if (
this != pos.m_object)
3237 throw std::domain_error(
"iterator does not fit current value");
3240 InteratorType result =
end();
3249 if (not pos.m_it.primitive_iterator.is_begin())
3251 throw std::out_of_range(
"iterator out of range");
3256 delete m_value.string;
3257 m_value.string =
nullptr;
3266 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3272 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3278 throw std::domain_error(
"cannot use erase() with " + type_name());
3327 template <
class InteratorType,
typename
3329 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3330 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3333 InteratorType
erase(InteratorType first, InteratorType last)
3336 if (
this != first.m_object or
this != last.m_object)
3338 throw std::domain_error(
"iterators do not fit current value");
3341 InteratorType result =
end();
3350 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3352 throw std::out_of_range(
"iterators out of range");
3357 delete m_value.string;
3358 m_value.string =
nullptr;
3367 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3368 last.m_it.object_iterator);
3374 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3375 last.m_it.array_iterator);
3381 throw std::domain_error(
"cannot use erase with " + type_name());
3418 return m_value.object->erase(key);
3422 throw std::domain_error(
"cannot use erase() with " + type_name());
3455 throw std::out_of_range(
"index out of range");
3458 m_value.array->erase(m_value.array->begin() +
static_cast<difference_type>(idx));
3462 throw std::domain_error(
"cannot use erase() with " + type_name());
3485 auto result =
end();
3489 result.m_it.object_iterator = m_value.object->find(key);
3501 auto result =
cend();
3505 result.m_it.object_iterator = m_value.object->find(key);
3532 return is_object() ? m_value.object->count(key) : 0;
3772 template<
typename IteratorType>
class iteration_proxy;
3785 return iteration_proxy<iterator>(cont);
3793 return iteration_proxy<const_iterator>(cont);
3847 return m_value.array->empty();
3852 return m_value.object->empty();
3904 return m_value.array->size();
3909 return m_value.object->size();
3958 return m_value.array->max_size();
3963 return m_value.object->max_size();
4015 m_value.number_integer = 0;
4021 m_value.number_float = 0.0;
4027 m_value.boolean =
false;
4033 m_value.string->clear();
4039 m_value.array->clear();
4045 m_value.object->clear();
4080 throw std::domain_error(
"cannot use push_back() with " + type_name());
4091 m_value.array->push_back(std::move(val));
4115 throw std::domain_error(
"cannot use push_back() with " + type_name());
4126 m_value.array->push_back(val);
4164 throw std::domain_error(
"cannot use push_back() with " + type_name());
4175 m_value.object->insert(val);
4214 if (pos.m_object !=
this)
4216 throw std::domain_error(
"iterator does not fit current value");
4221 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4226 throw std::domain_error(
"cannot use insert() with " + type_name());
4267 if (pos.m_object !=
this)
4269 throw std::domain_error(
"iterator does not fit current value");
4274 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4279 throw std::domain_error(
"cannot use insert() with " + type_name());
4314 throw std::domain_error(
"cannot use insert() with " + type_name());
4318 if (pos.m_object !=
this)
4320 throw std::domain_error(
"iterator does not fit current value");
4323 if (first.m_object != last.m_object)
4325 throw std::domain_error(
"iterators do not fit");
4328 if (first.m_object ==
this or last.m_object ==
this)
4330 throw std::domain_error(
"passed iterators may not belong to container");
4335 result.m_it.array_iterator = m_value.array->insert(
4336 pos.m_it.array_iterator,
4337 first.m_it.array_iterator,
4338 last.m_it.array_iterator);
4368 throw std::domain_error(
"cannot use insert() with " + type_name());
4372 if (pos.m_object !=
this)
4374 throw std::domain_error(
"iterator does not fit current value");
4379 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4401 std::is_nothrow_move_constructible<value_t>::value and
4402 std::is_nothrow_move_assignable<value_t>::value and
4403 std::is_nothrow_move_constructible<json_value>::value and
4404 std::is_nothrow_move_assignable<json_value>::value
4407 std::swap(m_type, other.m_type);
4408 std::swap(m_value, other.m_value);
4435 std::swap(*(m_value.array), other);
4439 throw std::domain_error(
"cannot use swap() with " + type_name());
4467 std::swap(*(m_value.object), other);
4471 throw std::domain_error(
"cannot use swap() with " + type_name());
4499 std::swap(*(m_value.string), other);
4503 throw std::domain_error(
"cannot use swap() with " + type_name());
4529 static constexpr std::array<uint8_t, 7> order = {{
4546 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
4575 const auto lhs_type = lhs.type();
4576 const auto rhs_type = rhs.type();
4578 if (lhs_type == rhs_type)
4583 return *lhs.m_value.array == *rhs.m_value.array;
4585 return *lhs.m_value.object == *rhs.m_value.object;
4589 return *lhs.m_value.string == *rhs.m_value.string;
4591 return lhs.m_value.boolean == rhs.m_value.boolean;
4593 return lhs.m_value.number_integer == rhs.m_value.number_integer;
4595 return approx(lhs.m_value.number_float, rhs.m_value.number_float);
4602 return approx(static_cast<number_float_t>(lhs.m_value.number_integer),
4603 rhs.m_value.number_float);
4607 return approx(lhs.m_value.number_float,
4608 static_cast<number_float_t>(rhs.m_value.number_integer));
4663 return not (lhs == rhs);
4695 return not v.is_null();
4724 const auto lhs_type = lhs.type();
4725 const auto rhs_type = rhs.type();
4727 if (lhs_type == rhs_type)
4732 return *lhs.m_value.array < *rhs.m_value.array;
4734 return *lhs.m_value.object < *rhs.m_value.object;
4738 return *lhs.m_value.string < *rhs.m_value.string;
4740 return lhs.m_value.boolean < rhs.m_value.boolean;
4742 return lhs.m_value.number_integer < rhs.m_value.number_integer;
4744 return lhs.m_value.number_float < rhs.m_value.number_float;
4752 rhs.m_value.number_float;
4756 return lhs.m_value.number_float <
4785 return not (rhs < lhs);
4807 return not (lhs <= rhs);
4829 return not (lhs < rhs);
4864 friend std::ostream&
operator<<(std::ostream& o,
const basic_json& j)
4867 const bool pretty_print = (o.width() > 0);
4868 const auto indentation = (pretty_print ? o.width() : 0);
4874 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
4882 friend std::ostream&
operator>>(
const basic_json& j, std::ostream& o)
4923 return parser(s, cb).
parse();
4952 return parser(i, cb).
parse();
4960 return parser(i, cb).
parse();
4988 j = parser(i).
parse();
4998 j = parser(i).
parse();
5040 static std::size_t extra_space(
const string_t& s) noexcept
5042 std::size_t result = 0;
5044 for (
const auto& c : s)
5063 if (c >= 0x00 and c <= 0x1f)
5091 const auto space = extra_space(s);
5098 string_t result(s.size() + space,
'\\');
5099 std::size_t pos = 0;
5101 for (
const auto& c : s)
5108 result[pos + 1] =
'"';
5124 result[pos + 1] =
'b';
5132 result[pos + 1] =
'f';
5140 result[pos + 1] =
'n';
5148 result[pos + 1] =
'r';
5156 result[pos + 1] =
't';
5163 if (c >= 0x00 and c <= 0x1f)
5166 auto hexify = [](
const char v) ->
char
5168 return (v < 10) ? (
'0' + v) : (
'a' + v - 10);
5173 {
'u',
'0',
'0', hexify(c >> 4), hexify(c & 0x0f)
5211 void dump(std::ostream& o,
5212 const bool pretty_print,
5213 const unsigned int indent_step,
5214 const unsigned int current_indent = 0)
const
5217 unsigned int new_indent = current_indent;
5223 if (m_value.object->empty())
5234 new_indent += indent_step;
5238 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5240 if (i != m_value.object->cbegin())
5242 o << (pretty_print ?
",\n" :
",");
5244 o <<
string_t(new_indent,
' ') <<
"\""
5245 << escape_string(i->first) <<
"\":"
5246 << (pretty_print ?
" " :
"");
5247 i->second.dump(o, pretty_print, indent_step, new_indent);
5253 new_indent -= indent_step;
5257 o <<
string_t(new_indent,
' ') +
"}";
5263 if (m_value.array->empty())
5274 new_indent += indent_step;
5278 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5280 if (i != m_value.array->cbegin())
5282 o << (pretty_print ?
",\n" :
",");
5285 i->dump(o, pretty_print, indent_step, new_indent);
5291 new_indent -= indent_step;
5295 o <<
string_t(new_indent,
' ') <<
"]";
5301 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
5307 o << (m_value.boolean ?
"true" :
"false");
5313 o << m_value.number_integer;
5322 o << std::setprecision(std::numeric_limits<number_float_t>::digits10) << m_value.number_float;
5349 json_value m_value = {};
5366 class primitive_iterator_t
5382 bool is_begin()
const
5384 return (m_it == begin_value);
5390 return (m_it == end_value);
5410 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5420 struct internal_iterator
5423 typename object_t::iterator object_iterator;
5425 typename array_t::iterator array_iterator;
5427 primitive_iterator_t primitive_iterator;
5431 : object_iterator(), array_iterator(), primitive_iterator()
5449 class const_iterator :
public std::iterator<std::random_access_iterator_tag, const basic_json>
5452 friend class basic_json;
5472 switch (m_object->m_type)
5476 m_it.object_iterator =
typename object_t::iterator();
5482 m_it.array_iterator =
typename array_t::iterator();
5488 m_it.primitive_iterator = primitive_iterator_t();
5497 switch (m_object->m_type)
5501 m_it.object_iterator = other.m_it.object_iterator;
5507 m_it.array_iterator = other.m_it.array_iterator;
5513 m_it.primitive_iterator = other.m_it.primitive_iterator;
5521 : m_object(other.m_object), m_it(other.m_it)
5526 std::is_nothrow_move_constructible<pointer>::value and
5527 std::is_nothrow_move_assignable<pointer>::value and
5528 std::is_nothrow_move_constructible<internal_iterator>::value and
5529 std::is_nothrow_move_assignable<internal_iterator>::value
5532 std::swap(m_object, other.m_object);
5533 std::swap(m_it, other.m_it);
5541 switch (m_object->m_type)
5545 m_it.object_iterator = m_object->m_value.object->begin();
5551 m_it.array_iterator = m_object->m_value.array->begin();
5558 m_it.primitive_iterator.set_end();
5564 m_it.primitive_iterator.set_begin();
5573 switch (m_object->m_type)
5577 m_it.object_iterator = m_object->m_value.object->end();
5583 m_it.array_iterator = m_object->m_value.array->end();
5589 m_it.primitive_iterator.set_end();
5599 switch (m_object->m_type)
5603 return m_it.object_iterator->second;
5608 return *m_it.array_iterator;
5613 throw std::out_of_range(
"cannot get value");
5618 if (m_it.primitive_iterator.is_begin())
5624 throw std::out_of_range(
"cannot get value");
5633 switch (m_object->m_type)
5637 return &(m_it.object_iterator->second);
5642 return &*m_it.array_iterator;
5647 if (m_it.primitive_iterator.is_begin())
5653 throw std::out_of_range(
"cannot get value");
5662 auto result = *
this;
5670 switch (m_object->m_type)
5674 ++m_it.object_iterator;
5680 ++m_it.array_iterator;
5686 ++m_it.primitive_iterator;
5697 auto result = *
this;
5705 switch (m_object->m_type)
5709 --m_it.object_iterator;
5715 --m_it.array_iterator;
5721 --m_it.primitive_iterator;
5733 if (m_object != other.m_object)
5735 throw std::domain_error(
"cannot compare iterators of different containers");
5738 switch (m_object->m_type)
5742 return (m_it.object_iterator == other.m_it.object_iterator);
5747 return (m_it.array_iterator == other.m_it.array_iterator);
5752 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
5767 if (m_object != other.m_object)
5769 throw std::domain_error(
"cannot compare iterators of different containers");
5772 switch (m_object->m_type)
5776 throw std::domain_error(
"cannot use operator< for object iterators");
5781 return (m_it.array_iterator < other.m_it.array_iterator);
5786 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
5794 return not other.operator < (*this);
5812 switch (m_object->m_type)
5816 throw std::domain_error(
"cannot use operator+= for object iterators");
5821 m_it.array_iterator += i;
5827 m_it.primitive_iterator += i;
5844 auto result = *
this;
5852 auto result = *
this;
5860 switch (m_object->m_type)
5864 throw std::domain_error(
"cannot use operator- for object iterators");
5869 return m_it.array_iterator - other.m_it.array_iterator;
5874 return m_it.primitive_iterator - other.m_it.primitive_iterator;
5882 switch (m_object->m_type)
5886 throw std::domain_error(
"cannot use operator[] for object iterators");
5891 return *(m_it.array_iterator + n);
5896 throw std::out_of_range(
"cannot get value");
5901 if (m_it.primitive_iterator == -n)
5907 throw std::out_of_range(
"cannot get value");
5914 typename object_t::key_type
key()
const
5916 if (m_object->is_object())
5918 return m_it.object_iterator->first;
5922 throw std::domain_error(
"cannot use key() for non-object iterators");
5936 internal_iterator m_it = internal_iterator();
5972 std::is_nothrow_move_constructible<pointer>::value and
5973 std::is_nothrow_move_assignable<pointer>::value and
5974 std::is_nothrow_move_constructible<internal_iterator>::value and
5975 std::is_nothrow_move_assignable<internal_iterator>::value
6041 auto result = *
this;
6049 auto result = *
this;
6089 template<
typename Base>
6090 class json_reverse_iterator :
public std::reverse_iterator<Base>
6108 return base_iterator::operator++(1);
6114 base_iterator::operator++();
6121 return base_iterator::operator--(1);
6127 base_iterator::operator--();
6134 base_iterator::operator+=(i);
6141 auto result = *
this;
6149 auto result = *
this;
6157 return this->base() - other.base();
6167 typename object_t::key_type
key()
const
6169 auto it = --this->base();
6176 auto it = --this->base();
6177 return it.operator * ();
6184 template<
typename IteratorType>
6185 class iteration_proxy
6189 class iteration_proxy_internal
6193 IteratorType anchor;
6195 size_t array_index = 0;
6198 iteration_proxy_internal(IteratorType it)
6203 iteration_proxy_internal& operator*()
6209 iteration_proxy_internal& operator++()
6218 bool operator!= (
const iteration_proxy_internal& o)
6220 return anchor != o.anchor;
6226 switch (anchor.m_object->type())
6231 return std::to_string(array_index);
6237 return anchor.key();
6249 typename IteratorType::reference
value()
const
6251 return anchor.value();
6256 typename IteratorType::reference container;
6260 iteration_proxy(
typename IteratorType::reference cont)
6265 iteration_proxy_internal
begin()
6267 return iteration_proxy_internal(container.begin());
6271 iteration_proxy_internal
end()
6273 return iteration_proxy_internal(container.end());
6294 enum class token_type
6313 using lexer_char_t =
unsigned char;
6316 explicit lexer(
const string_t& s) noexcept
6317 : m_stream(
nullptr), m_buffer(s)
6319 m_content =
reinterpret_cast<const lexer_char_t*
>(s.c_str());
6320 m_start = m_cursor = m_content;
6321 m_limit = m_content + s.size();
6323 explicit lexer(std::istream* s) noexcept
6324 : m_stream(s), m_buffer()
6326 getline(*m_stream, m_buffer);
6327 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
6328 m_start = m_cursor = m_content;
6329 m_limit = m_content + m_buffer.size();
6336 lexer(
const lexer&) =
delete;
6350 static string_t to_unicode(
const std::size_t codepoint1,
6351 const std::size_t codepoint2 = 0)
6356 std::size_t codepoint = codepoint1;
6359 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6362 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6376 throw std::invalid_argument(
"missing or wrong low surrogate");
6380 if (codepoint < 0x80)
6383 result.append(1, static_cast<typename string_t::value_type>(codepoint));
6385 else if (codepoint <= 0x7ff)
6388 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
6389 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6391 else if (codepoint <= 0xffff)
6394 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
6395 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6396 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6398 else if (codepoint <= 0x10ffff)
6401 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
6402 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
6403 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6404 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6408 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
6415 static std::string token_type_name(token_type t)
6419 case token_type::uninitialized:
6420 return "<uninitialized>";
6421 case token_type::literal_true:
6422 return "true literal";
6423 case token_type::literal_false:
6424 return "false literal";
6425 case token_type::literal_null:
6426 return "null literal";
6427 case token_type::value_string:
6428 return "string literal";
6429 case token_type::value_number:
6430 return "number literal";
6431 case token_type::begin_array:
6433 case token_type::begin_object:
6435 case token_type::end_array:
6437 case token_type::end_object:
6439 case token_type::name_separator:
6441 case token_type::value_separator:
6443 case token_type::parse_error:
6444 return "<parse error>";
6445 case token_type::end_of_input:
6446 return "<end of input>";
6450 return "unknown token";
6465 token_type scan() noexcept
6476 unsigned int yyaccept = 0;
6477 static const unsigned char yybm[] =
6479 0, 0, 0, 0, 0, 0, 0, 0,
6480 0, 32, 32, 0, 0, 32, 0, 0,
6481 64, 64, 64, 64, 64, 64, 64, 64,
6482 64, 64, 64, 64, 64, 64, 64, 64,
6483 96, 64, 0, 64, 64, 64, 64, 64,
6484 64, 64, 64, 64, 64, 64, 64, 64,
6485 192, 192, 192, 192, 192, 192, 192, 192,
6486 192, 192, 64, 64, 64, 64, 64, 64,
6487 64, 64, 64, 64, 64, 64, 64, 64,
6488 64, 64, 64, 64, 64, 64, 64, 64,
6489 64, 64, 64, 64, 64, 64, 64, 64,
6490 64, 64, 64, 64, 0, 64, 64, 64,
6491 64, 64, 64, 64, 64, 64, 64, 64,
6492 64, 64, 64, 64, 64, 64, 64, 64,
6493 64, 64, 64, 64, 64, 64, 64, 64,
6494 64, 64, 64, 64, 64, 64, 64, 64,
6495 64, 64, 64, 64, 64, 64, 64, 64,
6496 64, 64, 64, 64, 64, 64, 64, 64,
6497 64, 64, 64, 64, 64, 64, 64, 64,
6498 64, 64, 64, 64, 64, 64, 64, 64,
6499 64, 64, 64, 64, 64, 64, 64, 64,
6500 64, 64, 64, 64, 64, 64, 64, 64,
6501 64, 64, 64, 64, 64, 64, 64, 64,
6502 64, 64, 64, 64, 64, 64, 64, 64,
6503 64, 64, 64, 64, 64, 64, 64, 64,
6504 64, 64, 64, 64, 64, 64, 64, 64,
6505 64, 64, 64, 64, 64, 64, 64, 64,
6506 64, 64, 64, 64, 64, 64, 64, 64,
6507 64, 64, 64, 64, 64, 64, 64, 64,
6508 64, 64, 64, 64, 64, 64, 64, 64,
6509 64, 64, 64, 64, 64, 64, 64, 64,
6510 64, 64, 64, 64, 64, 64, 64, 64,
6512 if ((m_limit - m_cursor) < 5)
6525 goto basic_json_parser_28;
6529 goto basic_json_parser_30;
6533 goto basic_json_parser_4;
6540 goto basic_json_parser_2;
6544 goto basic_json_parser_30;
6554 goto basic_json_parser_27;
6558 goto basic_json_parser_30;
6560 goto basic_json_parser_16;
6568 goto basic_json_parser_23;
6570 goto basic_json_parser_30;
6576 goto basic_json_parser_24;
6580 goto basic_json_parser_26;
6582 goto basic_json_parser_18;
6595 goto basic_json_parser_8;
6599 goto basic_json_parser_30;
6601 goto basic_json_parser_10;
6607 goto basic_json_parser_22;
6611 goto basic_json_parser_30;
6613 goto basic_json_parser_20;
6622 goto basic_json_parser_21;
6626 goto basic_json_parser_30;
6628 goto basic_json_parser_12;
6636 goto basic_json_parser_30;
6638 goto basic_json_parser_14;
6644 goto basic_json_parser_6;
6646 goto basic_json_parser_30;
6651 basic_json_parser_2:
6654 goto basic_json_parser_5;
6655 basic_json_parser_3:
6659 basic_json_parser_4:
6661 if (m_limit <= m_cursor)
6666 basic_json_parser_5:
6667 if (yybm[0 + yych] & 32)
6669 goto basic_json_parser_4;
6671 goto basic_json_parser_3;
6672 basic_json_parser_6:
6674 yych = *(m_marker = ++m_cursor);
6677 goto basic_json_parser_64;
6679 basic_json_parser_7:
6681 return token_type::parse_error;
6683 basic_json_parser_8:
6686 return token_type::begin_array;
6688 basic_json_parser_10:
6691 return token_type::end_array;
6693 basic_json_parser_12:
6696 return token_type::begin_object;
6698 basic_json_parser_14:
6701 return token_type::end_object;
6703 basic_json_parser_16:
6706 return token_type::value_separator;
6708 basic_json_parser_18:
6711 return token_type::name_separator;
6713 basic_json_parser_20:
6715 yych = *(m_marker = ++m_cursor);
6718 goto basic_json_parser_60;
6720 goto basic_json_parser_7;
6721 basic_json_parser_21:
6723 yych = *(m_marker = ++m_cursor);
6726 goto basic_json_parser_56;
6728 goto basic_json_parser_7;
6729 basic_json_parser_22:
6731 yych = *(m_marker = ++m_cursor);
6734 goto basic_json_parser_51;
6736 goto basic_json_parser_7;
6737 basic_json_parser_23:
6741 goto basic_json_parser_7;
6745 goto basic_json_parser_50;
6749 goto basic_json_parser_41;
6751 goto basic_json_parser_7;
6752 basic_json_parser_24:
6754 yych = *(m_marker = ++m_cursor);
6759 goto basic_json_parser_43;
6766 goto basic_json_parser_44;
6770 goto basic_json_parser_44;
6773 basic_json_parser_25:
6775 return token_type::value_number;
6777 basic_json_parser_26:
6779 yych = *(m_marker = ++m_cursor);
6780 goto basic_json_parser_42;
6781 basic_json_parser_27:
6783 yych = *(m_marker = ++m_cursor);
6786 goto basic_json_parser_7;
6788 goto basic_json_parser_32;
6789 basic_json_parser_28:
6792 return token_type::end_of_input;
6794 basic_json_parser_30:
6796 goto basic_json_parser_7;
6797 basic_json_parser_31:
6799 if (m_limit <= m_cursor)
6804 basic_json_parser_32:
6805 if (yybm[0 + yych] & 64)
6807 goto basic_json_parser_31;
6811 goto basic_json_parser_33;
6815 goto basic_json_parser_35;
6817 goto basic_json_parser_34;
6818 basic_json_parser_33:
6819 m_cursor = m_marker;
6822 goto basic_json_parser_7;
6826 goto basic_json_parser_25;
6828 basic_json_parser_34:
6830 if (m_limit <= m_cursor)
6841 goto basic_json_parser_31;
6845 goto basic_json_parser_33;
6847 goto basic_json_parser_31;
6855 goto basic_json_parser_33;
6857 goto basic_json_parser_31;
6863 goto basic_json_parser_31;
6865 goto basic_json_parser_33;
6875 goto basic_json_parser_31;
6879 goto basic_json_parser_31;
6881 goto basic_json_parser_33;
6889 goto basic_json_parser_31;
6891 goto basic_json_parser_33;
6897 goto basic_json_parser_31;
6901 goto basic_json_parser_37;
6903 goto basic_json_parser_33;
6907 basic_json_parser_35:
6910 return token_type::value_string;
6912 basic_json_parser_37:
6914 if (m_limit <= m_cursor)
6923 goto basic_json_parser_33;
6927 goto basic_json_parser_33;
6934 goto basic_json_parser_38;
6938 goto basic_json_parser_33;
6942 goto basic_json_parser_33;
6945 basic_json_parser_38:
6947 if (m_limit <= m_cursor)
6956 goto basic_json_parser_33;
6960 goto basic_json_parser_33;
6967 goto basic_json_parser_39;
6971 goto basic_json_parser_33;
6975 goto basic_json_parser_33;
6978 basic_json_parser_39:
6980 if (m_limit <= m_cursor)
6989 goto basic_json_parser_33;
6993 goto basic_json_parser_33;
7000 goto basic_json_parser_40;
7004 goto basic_json_parser_33;
7008 goto basic_json_parser_33;
7011 basic_json_parser_40:
7013 if (m_limit <= m_cursor)
7022 goto basic_json_parser_33;
7026 goto basic_json_parser_31;
7028 goto basic_json_parser_33;
7034 goto basic_json_parser_31;
7038 goto basic_json_parser_33;
7042 goto basic_json_parser_31;
7044 goto basic_json_parser_33;
7046 basic_json_parser_41:
7048 m_marker = ++m_cursor;
7049 if ((m_limit - m_cursor) < 3)
7054 basic_json_parser_42:
7055 if (yybm[0 + yych] & 128)
7057 goto basic_json_parser_41;
7063 goto basic_json_parser_25;
7070 goto basic_json_parser_44;
7074 goto basic_json_parser_44;
7076 goto basic_json_parser_25;
7078 basic_json_parser_43:
7082 goto basic_json_parser_33;
7086 goto basic_json_parser_48;
7088 goto basic_json_parser_33;
7089 basic_json_parser_44:
7095 goto basic_json_parser_33;
7102 goto basic_json_parser_45;
7106 goto basic_json_parser_33;
7110 goto basic_json_parser_46;
7112 goto basic_json_parser_33;
7114 basic_json_parser_45:
7118 goto basic_json_parser_33;
7122 goto basic_json_parser_33;
7124 basic_json_parser_46:
7126 if (m_limit <= m_cursor)
7133 goto basic_json_parser_25;
7137 goto basic_json_parser_46;
7139 goto basic_json_parser_25;
7140 basic_json_parser_48:
7142 m_marker = ++m_cursor;
7143 if ((m_limit - m_cursor) < 3)
7152 goto basic_json_parser_25;
7156 goto basic_json_parser_48;
7158 goto basic_json_parser_25;
7164 goto basic_json_parser_44;
7168 goto basic_json_parser_44;
7170 goto basic_json_parser_25;
7172 basic_json_parser_50:
7174 yych = *(m_marker = ++m_cursor);
7179 goto basic_json_parser_43;
7181 goto basic_json_parser_25;
7187 goto basic_json_parser_44;
7191 goto basic_json_parser_44;
7193 goto basic_json_parser_25;
7195 basic_json_parser_51:
7199 goto basic_json_parser_33;
7204 goto basic_json_parser_33;
7209 goto basic_json_parser_33;
7213 return token_type::literal_false;
7215 basic_json_parser_56:
7219 goto basic_json_parser_33;
7224 goto basic_json_parser_33;
7228 return token_type::literal_true;
7230 basic_json_parser_60:
7234 goto basic_json_parser_33;
7239 goto basic_json_parser_33;
7243 return token_type::literal_null;
7245 basic_json_parser_64:
7249 goto basic_json_parser_33;
7261 void yyfill() noexcept
7263 if (not m_stream or not * m_stream)
7268 const ssize_t offset_start = m_start - m_content;
7269 const ssize_t offset_marker = m_marker - m_start;
7270 const ssize_t offset_cursor = m_cursor - m_start;
7272 m_buffer.erase(0, static_cast<size_t>(offset_start));
7274 std::getline(*m_stream, line);
7275 m_buffer +=
"\n" + line;
7277 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
7278 m_start = m_content;
7279 m_marker = m_start + offset_marker;
7280 m_cursor = m_start + offset_cursor;
7281 m_limit = m_start + m_buffer.size() - 1;
7285 string_t get_token() const noexcept
7287 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7288 static_cast<size_t>(m_cursor - m_start));
7315 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7318 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7374 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7375 4).c_str(),
nullptr, 16);
7378 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7381 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
7383 throw std::invalid_argument(
"missing low surrogate");
7387 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7388 (i + 7), 4).c_str(),
nullptr, 16);
7389 result += to_unicode(codepoint, codepoint2);
7396 result += to_unicode(codepoint);
7408 result.append(1, static_cast<typename string_t::value_type>(*i));
7432 long double get_number()
const
7435 typename string_t::value_type* endptr;
7436 const auto float_val = std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start),
7441 return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
7446 std::istream* m_stream;
7450 const lexer_char_t* m_content =
nullptr;
7452 const lexer_char_t* m_start =
nullptr;
7454 const lexer_char_t* m_marker =
nullptr;
7456 const lexer_char_t* m_cursor =
nullptr;
7458 const lexer_char_t* m_limit =
nullptr;
7471 : callback(cb), m_lexer(s)
7479 : callback(cb), m_lexer(&_is)
7488 basic_json result = parse_internal(
true);
7490 expect(lexer::token_type::end_of_input);
7494 return result.is_discarded() ?
basic_json() : result;
7499 basic_json parse_internal(
bool keep)
7505 case lexer::token_type::begin_object:
7518 if (last_token == lexer::token_type::end_object)
7529 unexpect(lexer::token_type::value_separator);
7535 if (last_token == lexer::token_type::value_separator)
7541 expect(lexer::token_type::value_string);
7542 const auto key = m_lexer.get_string();
7544 bool keep_tag =
false;
7560 expect(lexer::token_type::name_separator);
7564 auto value = parse_internal(keep);
7565 if (keep and keep_tag and not
value.is_discarded())
7567 result[key] = std::move(
value);
7570 while (last_token == lexer::token_type::value_separator);
7573 expect(lexer::token_type::end_object);
7583 case lexer::token_type::begin_array:
7596 if (last_token == lexer::token_type::end_array)
7607 unexpect(lexer::token_type::value_separator);
7613 if (last_token == lexer::token_type::value_separator)
7619 auto value = parse_internal(keep);
7620 if (keep and not
value.is_discarded())
7622 result.push_back(std::move(
value));
7625 while (last_token == lexer::token_type::value_separator);
7628 expect(lexer::token_type::end_array);
7638 case lexer::token_type::literal_null:
7645 case lexer::token_type::value_string:
7647 const auto s = m_lexer.get_string();
7653 case lexer::token_type::literal_true:
7657 result.m_value =
true;
7661 case lexer::token_type::literal_false:
7665 result.m_value =
false;
7669 case lexer::token_type::value_number:
7671 auto float_val = m_lexer.get_number();
7675 if (std::isnan(float_val))
7677 throw std::invalid_argument(std::string(
"parse error - ") +
7678 m_lexer.get_token() +
" is not a number");
7685 if (approx(float_val, static_cast<long double>(int_val)))
7689 result.m_value = int_val;
7703 unexpect(last_token);
7715 typename lexer::token_type get_token()
7717 last_token = m_lexer.scan();
7721 void expect(
typename lexer::token_type t)
const
7723 if (t != last_token)
7725 std::string error_msg =
"parse error - unexpected \'";
7726 error_msg += m_lexer.get_token();
7727 error_msg +=
"\' (" + lexer::token_type_name(last_token);
7728 error_msg +=
"); expected " + lexer::token_type_name(t);
7729 throw std::invalid_argument(error_msg);
7733 void unexpect(
typename lexer::token_type t)
const
7735 if (t == last_token)
7737 std::string error_msg =
"parse error - unexpected \'";
7738 error_msg += m_lexer.get_token();
7739 error_msg +=
"\' (";
7740 error_msg += lexer::token_type_name(last_token) +
")";
7741 throw std::invalid_argument(error_msg);
7751 typename lexer::token_type last_token = lexer::token_type::uninitialized;
7789 is_nothrow_move_constructible<nlohmann::json>::value and
7790 is_nothrow_move_assignable<nlohmann::json>::value
7808 const auto& h = hash<nlohmann::json::string_t>();
7826 inline nlohmann::json operator "" _json(
const char* s, std::size_t)
7829 (const_cast<char*>(s)));
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
bool operator!=(const const_iterator &other) const
comparison: not equal
iterator insert(const_iterator pos, basic_json &&val)
inserts element
iterator operator++(int)
post-increment (it++)
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
json_reverse_iterator operator-(difference_type i) const
subtract from 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_reference operator[](size_type idx) const
access specified array element
reference operator[](const T(&key)[n])
access specified object element
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
const_iterator & operator--()
pre-decrement (–it)
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
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
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
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
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
json_reverse_iterator operator--(int)
post-decrement (it–)
StringType string_t
a type for a string
void push_back(const typename object_t::value_type &val)
add an object to an object
basic_json(boolean_t val)
create a boolean (explicit)
static basic_json array(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an array from an initializer list
iterator & operator++()
pre-increment (++it)
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
const_iterator & operator++()
pre-increment (++it)
difference_type operator-(const json_reverse_iterator &other) const
return difference
basic_json<> json
default JSON class
reference front()
access the first element
bool is_array() const noexcept
return whether value is an array
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
json_reverse_iterator(const typename base_iterator::iterator_type &it)
create reverse iterator from iterator
a class to store JSON values
json_reverse_iterator & operator--()
pre-decrement (–it)
basic_json(const object_t &val)
create an object (explicit)
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
void push_back(basic_json &&val)
add an object to an array
const_iterator cbegin() const
returns a const iterator to the first element
bool is_string() const noexcept
return whether value is a string
iterator & operator+=(difference_type i)
add to iterator
const PointerType get_ptr() const noexcept
get a pointer value (implicit)
basic_json(const CompatibleStringType &val)
create a string (implicit)
the parser read ] and finished processing a JSON array
const_iterator base_iterator
reference operator+=(basic_json &&val)
add an object to an array
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
a mutable random access iterator for the basic_json class
iterator & operator-=(difference_type i)
subtract from iterator
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
reference operator[](const typename object_t::key_type &key)
access specified object element
difference_type operator-(const iterator &other) const
reference value() const
return the value of an iterator
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
const_iterator end() const
returns a const iterator to one past the last element
const_iterator(const const_iterator &other) noexcept
copy constructor
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
object_t::key_type key() const
return the key of an object iterator
iterator end()
returns an 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
reference operator*()
return a reference to the value pointed to by the iterator
reverse_iterator rend()
returns an iterator to the reverse-end
bool is_object() const noexcept
return whether value is an object
const_iterator operator-(difference_type i)
subtract from iterator
bool is_discarded() const noexcept
return whether value is discarded
basic_json(const CompatibleArrayType &val)
create an array (implicit)
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
const_reverse_iterator rend() const
returns a const reverse iterator to one before the first
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
bool is_boolean() const noexcept
return whether value is a boolean
iterator begin()
returns an iterator to the first element
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
reference operator+=(const basic_json &val)
add an object to an array
AllocatorType< basic_json > allocator_type
the allocator type
basic_json(const number_float_t val)
create a floating-point number (explicit)
bool is_number_integer() const noexcept
return whether value is an integer number
iterator operator+(difference_type i)
add to iterator
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
basic_json(const typename string_t::value_type *val)
create a string (explicit)
const_iterator()=default
default constructor
the parser read [ and started to process a JSON array
iterator find(typename object_t::key_type key)
find an element in a JSON object
basic_json(const value_t value_type)
create an empty value with a given type
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
iterator & operator--()
pre-decrement (–it)
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
pointer operator->() const
dereference the iterator
discarded by the the parser callback function
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
const_iterator cend() const
returns a const iterator to one past the last element
typename Base::reference reference
the reference type for the pointed-to element
size_type size() const noexcept
returns the number of elements
static allocator_type get_allocator()
returns the allocator associated with the container
object (unordered set of name/value pairs)
reference at(size_type idx)
access specified array element with bounds checking
the parser read } and finished processing a JSON object
iterator()=default
default constructor
json_reverse_iterator(const base_iterator &it)
create reverse iterator from base class
value_t type() const noexcept
return the type of the JSON value (explicit)
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
object_t::key_type key() const
return the key of an object iterator
bool is_structured() const noexcept
return whether type is structured
namespace for Niels Lohmann
typename basic_json::difference_type difference_type
a type to represent differences between iterators
void swap(array_t &other)
exchanges the values
reverse_iterator rbegin()
returns an iterator to the reverse-beginning
reference operator+=(const typename object_t::value_type &val)
add an object to an object
reference operator[](difference_type n) const
access to successor
std::size_t size_type
a type to represent container sizes
const_reverse_iterator rbegin() const
returns a const reverse iterator to the last element
basic_json(const basic_json &other)
copy constructor
const_iterator operator+(difference_type i)
add to iterator
value_t
the JSON type enumeration
const value_type & const_reference
the type of an element const reference
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
bool is_null() const noexcept
return whether value is null
void swap(string_t &other)
exchanges the values
reference value() const
return the value of an iterator
const_iterator operator--(int)
post-decrement (it–)
void erase(const size_type idx)
remove element from a JSON array given an index
void clear() noexcept
clears the contents
pointer operator->()
dereference the iterator
basic_json value_type
the type of elements in a basic_json container
array (ordered collection of values)
const_reference front() const
access the first element
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
std::ptrdiff_t difference_type
a type to represent differences between iterators
const_iterator & operator+=(difference_type i)
add to 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
difference_type operator-(const const_iterator &other) const
return difference
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
bool is_number() const noexcept
return whether value is a number
BooleanType boolean_t
a type for a boolean
const_reverse_iterator crend() const
returns a const reverse iterator to one before the first
basic_json() noexcept=default
create a null object (implicitly)
the parser read a key of a value in an object
bool empty() const noexcept
checks whether the container is empty
string_t value(const typename object_t::key_type &key, const char *default_value) const
overload for a default value of type const char*
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
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
const_reverse_iterator crbegin() const
returns a const reverse iterator to the last element
reference value() const
return the value of an iterator
const_iterator(pointer object)
constructor for a given JSON instance
friend bool operator<(const value_t lhs, const value_t rhs)
comparison operator for JSON types
iterator(pointer object) noexcept
constructor for a given JSON instance
bool operator<(const const_iterator &other) const
comparison: smaller
string_t dump(const int indent=-1) const
serialization
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
const_iterator & operator-=(difference_type i)
subtract from iterator
basic_json(const int val)
create an integer number from an enum type (explicit)
basic_json(const array_t &val)
create an array (explicit)
number value (floating-point)
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
json_reverse_iterator operator++(int)
post-increment (it++)
PointerType get_ptr() noexcept
get a pointer value (implicit)
const_iterator(const iterator &other)
copy constructor given a nonconst iterator
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
InteratorType erase(InteratorType pos)
remove element given an iterator
bool operator<=(const const_iterator &other) const
comparison: less than or equal
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
reference back()
access the last element
bool is_number_float() const noexcept
return whether value is a floating-point number
the parser read { and started to process a JSON object
const_iterator operator++(int)
post-increment (it++)
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
basic_json(const string_t &val)
create a string (explicit)
iterator(const iterator &other) noexcept
copy constructor
const_reference back() const
access the last element
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
size_type count(typename object_t::key_type key) const
returns the number of occurrences of a key in a JSON object
size_type max_size() const noexcept
returns the maximum possible number of elements
void push_back(const basic_json &val)
add an object to an array
bool operator==(const const_iterator &other) const
comparison: equal
json_reverse_iterator & operator++()
pre-increment (++it)
bool operator>(const const_iterator &other) const
comparison: greater than
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
basic_json(basic_json &&other) noexcept
move constructor
const_reference operator[](const T(&key)[n]) const
read-only access specified object element
const_iterator begin() const
returns a const iterator to the first element
const_reference at(size_type idx) const
access specified array element with bounds checking
json_reverse_iterator & operator+=(difference_type i)
add to iterator
a const random access iterator for the basic_json class
a template for a reverse iterator class
void swap(object_t &other)
exchanges the values
std::bidirectional_iterator_tag iterator_category
the category of the iterator
bool is_primitive() const noexcept
return whether type is primitive
iterator insert(const_iterator pos, const basic_json &val)
inserts element
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
reference operator[](difference_type n) const
access to successor
NumberIntegerType number_integer_t
a type for a number (integer)
reference operator[](difference_type n) const
access to successor
reference operator*() const
return a reference to the value pointed to by the iterator
value_type & reference
the type of an element reference
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
the parser finished reading a JSON value
NumberFloatType number_float_t
a type for a number (floating-point)
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
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
basic_json(const CompatibleObjectType &val)
create an object (implicit)
reference operator[](size_type idx)
access specified array element
iterator operator--(int)
post-decrement (it–)
json_reverse_iterator operator+(difference_type i) const
add to iterator
parse_event_t
JSON callback events.
iterator operator-(difference_type i)
subtract from iterator