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;
3821 return m_value.array->empty();
3826 return m_value.object->empty();
3878 return m_value.array->size();
3883 return m_value.object->size();
3932 return m_value.array->max_size();
3937 return m_value.object->max_size();
3989 m_value.number_integer = 0;
3995 m_value.number_float = 0.0;
4001 m_value.boolean =
false;
4007 m_value.string->clear();
4013 m_value.array->clear();
4019 m_value.object->clear();
4054 throw std::domain_error(
"cannot use push_back() with " + type_name());
4065 m_value.array->push_back(std::move(val));
4089 throw std::domain_error(
"cannot use push_back() with " + type_name());
4100 m_value.array->push_back(val);
4138 throw std::domain_error(
"cannot use push_back() with " + type_name());
4149 m_value.object->insert(val);
4188 if (pos.m_object !=
this)
4190 throw std::domain_error(
"iterator does not fit current value");
4195 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4200 throw std::domain_error(
"cannot use insert() with " + type_name());
4241 if (pos.m_object !=
this)
4243 throw std::domain_error(
"iterator does not fit current value");
4248 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4253 throw std::domain_error(
"cannot use insert() with " + type_name());
4288 throw std::domain_error(
"cannot use insert() with " + type_name());
4292 if (pos.m_object !=
this)
4294 throw std::domain_error(
"iterator does not fit current value");
4297 if (first.m_object != last.m_object)
4299 throw std::domain_error(
"iterators do not fit");
4302 if (first.m_object ==
this or last.m_object ==
this)
4304 throw std::domain_error(
"passed iterators may not belong to container");
4309 result.m_it.array_iterator = m_value.array->insert(
4310 pos.m_it.array_iterator,
4311 first.m_it.array_iterator,
4312 last.m_it.array_iterator);
4342 throw std::domain_error(
"cannot use insert() with " + type_name());
4346 if (pos.m_object !=
this)
4348 throw std::domain_error(
"iterator does not fit current value");
4353 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4375 std::is_nothrow_move_constructible<value_t>::value and
4376 std::is_nothrow_move_assignable<value_t>::value and
4377 std::is_nothrow_move_constructible<json_value>::value and
4378 std::is_nothrow_move_assignable<json_value>::value
4381 std::swap(m_type, other.m_type);
4382 std::swap(m_value, other.m_value);
4409 std::swap(*(m_value.array), other);
4413 throw std::domain_error(
"cannot use swap() with " + type_name());
4441 std::swap(*(m_value.object), other);
4445 throw std::domain_error(
"cannot use swap() with " + type_name());
4473 std::swap(*(m_value.string), other);
4477 throw std::domain_error(
"cannot use swap() with " + type_name());
4503 static constexpr std::array<uint8_t, 7> order = {{
4520 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
4549 const auto lhs_type = lhs.type();
4550 const auto rhs_type = rhs.type();
4552 if (lhs_type == rhs_type)
4557 return *lhs.m_value.array == *rhs.m_value.array;
4559 return *lhs.m_value.object == *rhs.m_value.object;
4563 return *lhs.m_value.string == *rhs.m_value.string;
4565 return lhs.m_value.boolean == rhs.m_value.boolean;
4567 return lhs.m_value.number_integer == rhs.m_value.number_integer;
4569 return approx(lhs.m_value.number_float, rhs.m_value.number_float);
4576 return approx(static_cast<number_float_t>(lhs.m_value.number_integer),
4577 rhs.m_value.number_float);
4581 return approx(lhs.m_value.number_float,
4582 static_cast<number_float_t>(rhs.m_value.number_integer));
4637 return not (lhs == rhs);
4669 return not v.is_null();
4698 const auto lhs_type = lhs.type();
4699 const auto rhs_type = rhs.type();
4701 if (lhs_type == rhs_type)
4706 return *lhs.m_value.array < *rhs.m_value.array;
4708 return *lhs.m_value.object < *rhs.m_value.object;
4712 return *lhs.m_value.string < *rhs.m_value.string;
4714 return lhs.m_value.boolean < rhs.m_value.boolean;
4716 return lhs.m_value.number_integer < rhs.m_value.number_integer;
4718 return lhs.m_value.number_float < rhs.m_value.number_float;
4726 rhs.m_value.number_float;
4730 return lhs.m_value.number_float <
4759 return not (rhs < lhs);
4781 return not (lhs <= rhs);
4803 return not (lhs < rhs);
4838 friend std::ostream&
operator<<(std::ostream& o,
const basic_json& j)
4841 const bool pretty_print = (o.width() > 0);
4842 const auto indentation = (pretty_print ? o.width() : 0);
4848 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
4856 friend std::ostream&
operator>>(
const basic_json& j, std::ostream& o)
4897 return parser(s, cb).
parse();
4926 return parser(i, cb).
parse();
4934 return parser(i, cb).
parse();
4962 j = parser(i).
parse();
4972 j = parser(i).
parse();
5014 static std::size_t extra_space(
const string_t& s) noexcept
5016 std::size_t result = 0;
5018 for (
const auto& c : s)
5037 if (c >= 0x00 and c <= 0x1f)
5065 const auto space = extra_space(s);
5072 string_t result(s.size() + space,
'\\');
5073 std::size_t pos = 0;
5075 for (
const auto& c : s)
5082 result[pos + 1] =
'"';
5098 result[pos + 1] =
'b';
5106 result[pos + 1] =
'f';
5114 result[pos + 1] =
'n';
5122 result[pos + 1] =
'r';
5130 result[pos + 1] =
't';
5137 if (c >= 0x00 and c <= 0x1f)
5140 auto hexify = [](
const char v) ->
char
5142 return (v < 10) ? (
'0' + v) : (
'a' + v - 10);
5147 {
'u',
'0',
'0', hexify(c >> 4), hexify(c & 0x0f)
5185 void dump(std::ostream& o,
5186 const bool pretty_print,
5187 const unsigned int indent_step,
5188 const unsigned int current_indent = 0)
const
5191 unsigned int new_indent = current_indent;
5197 if (m_value.object->empty())
5208 new_indent += indent_step;
5212 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5214 if (i != m_value.object->cbegin())
5216 o << (pretty_print ?
",\n" :
",");
5218 o <<
string_t(new_indent,
' ') <<
"\""
5219 << escape_string(i->first) <<
"\":"
5220 << (pretty_print ?
" " :
"");
5221 i->second.dump(o, pretty_print, indent_step, new_indent);
5227 new_indent -= indent_step;
5231 o <<
string_t(new_indent,
' ') +
"}";
5237 if (m_value.array->empty())
5248 new_indent += indent_step;
5252 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5254 if (i != m_value.array->cbegin())
5256 o << (pretty_print ?
",\n" :
",");
5259 i->dump(o, pretty_print, indent_step, new_indent);
5265 new_indent -= indent_step;
5269 o <<
string_t(new_indent,
' ') <<
"]";
5275 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
5281 o << (m_value.boolean ?
"true" :
"false");
5287 o << m_value.number_integer;
5296 o << std::setprecision(std::numeric_limits<number_float_t>::digits10) << m_value.number_float;
5323 json_value m_value = {};
5340 class primitive_iterator_t
5356 bool is_begin()
const
5358 return (m_it == begin_value);
5364 return (m_it == end_value);
5384 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5394 struct internal_iterator
5397 typename object_t::iterator object_iterator;
5399 typename array_t::iterator array_iterator;
5401 primitive_iterator_t primitive_iterator;
5405 : object_iterator(), array_iterator(), primitive_iterator()
5423 class const_iterator :
public std::iterator<std::random_access_iterator_tag, const basic_json>
5426 friend class basic_json;
5446 switch (m_object->m_type)
5450 m_it.object_iterator =
typename object_t::iterator();
5456 m_it.array_iterator =
typename array_t::iterator();
5462 m_it.primitive_iterator = primitive_iterator_t();
5471 switch (m_object->m_type)
5475 m_it.object_iterator = other.m_it.object_iterator;
5481 m_it.array_iterator = other.m_it.array_iterator;
5487 m_it.primitive_iterator = other.m_it.primitive_iterator;
5495 : m_object(other.m_object), m_it(other.m_it)
5500 std::is_nothrow_move_constructible<pointer>::value and
5501 std::is_nothrow_move_assignable<pointer>::value and
5502 std::is_nothrow_move_constructible<internal_iterator>::value and
5503 std::is_nothrow_move_assignable<internal_iterator>::value
5506 std::swap(m_object, other.m_object);
5507 std::swap(m_it, other.m_it);
5515 switch (m_object->m_type)
5519 m_it.object_iterator = m_object->m_value.object->begin();
5525 m_it.array_iterator = m_object->m_value.array->begin();
5532 m_it.primitive_iterator.set_end();
5538 m_it.primitive_iterator.set_begin();
5547 switch (m_object->m_type)
5551 m_it.object_iterator = m_object->m_value.object->end();
5557 m_it.array_iterator = m_object->m_value.array->end();
5563 m_it.primitive_iterator.set_end();
5573 switch (m_object->m_type)
5577 return m_it.object_iterator->second;
5582 return *m_it.array_iterator;
5587 throw std::out_of_range(
"cannot get value");
5592 if (m_it.primitive_iterator.is_begin())
5598 throw std::out_of_range(
"cannot get value");
5607 switch (m_object->m_type)
5611 return &(m_it.object_iterator->second);
5616 return &*m_it.array_iterator;
5621 if (m_it.primitive_iterator.is_begin())
5627 throw std::out_of_range(
"cannot get value");
5636 auto result = *
this;
5644 switch (m_object->m_type)
5648 ++m_it.object_iterator;
5654 ++m_it.array_iterator;
5660 ++m_it.primitive_iterator;
5671 auto result = *
this;
5679 switch (m_object->m_type)
5683 --m_it.object_iterator;
5689 --m_it.array_iterator;
5695 --m_it.primitive_iterator;
5707 if (m_object != other.m_object)
5709 throw std::domain_error(
"cannot compare iterators of different containers");
5712 switch (m_object->m_type)
5716 return (m_it.object_iterator == other.m_it.object_iterator);
5721 return (m_it.array_iterator == other.m_it.array_iterator);
5726 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
5741 if (m_object != other.m_object)
5743 throw std::domain_error(
"cannot compare iterators of different containers");
5746 switch (m_object->m_type)
5750 throw std::domain_error(
"cannot use operator< for object iterators");
5755 return (m_it.array_iterator < other.m_it.array_iterator);
5760 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
5768 return not other.operator < (*this);
5786 switch (m_object->m_type)
5790 throw std::domain_error(
"cannot use operator+= for object iterators");
5795 m_it.array_iterator += i;
5801 m_it.primitive_iterator += i;
5818 auto result = *
this;
5826 auto result = *
this;
5834 switch (m_object->m_type)
5838 throw std::domain_error(
"cannot use operator- for object iterators");
5843 return m_it.array_iterator - other.m_it.array_iterator;
5848 return m_it.primitive_iterator - other.m_it.primitive_iterator;
5856 switch (m_object->m_type)
5860 throw std::domain_error(
"cannot use operator[] for object iterators");
5865 return *(m_it.array_iterator + n);
5870 throw std::out_of_range(
"cannot get value");
5875 if (m_it.primitive_iterator == -n)
5881 throw std::out_of_range(
"cannot get value");
5888 typename object_t::key_type
key()
const
5890 if (m_object->is_object())
5892 return m_it.object_iterator->first;
5896 throw std::domain_error(
"cannot use key() for non-object iterators");
5910 internal_iterator m_it = internal_iterator();
5946 std::is_nothrow_move_constructible<pointer>::value and
5947 std::is_nothrow_move_assignable<pointer>::value and
5948 std::is_nothrow_move_constructible<internal_iterator>::value and
5949 std::is_nothrow_move_assignable<internal_iterator>::value
6015 auto result = *
this;
6023 auto result = *
this;
6063 template<
typename Base>
6064 class json_reverse_iterator :
public std::reverse_iterator<Base>
6082 return base_iterator::operator++(1);
6088 base_iterator::operator++();
6095 return base_iterator::operator--(1);
6101 base_iterator::operator--();
6108 base_iterator::operator+=(i);
6115 auto result = *
this;
6123 auto result = *
this;
6131 return this->base() - other.base();
6141 typename object_t::key_type
key()
const
6143 auto it = --this->base();
6150 auto it = --this->base();
6151 return it.operator * ();
6158 template<
typename IteratorType>
6159 class iteration_proxy
6163 class iteration_proxy_internal
6167 IteratorType anchor;
6169 size_t array_index = 0;
6172 iteration_proxy_internal(IteratorType it)
6177 iteration_proxy_internal& operator*()
6183 iteration_proxy_internal& operator++()
6192 bool operator!= (
const iteration_proxy_internal& o)
6194 return anchor != o.anchor;
6200 switch (anchor.m_object->type())
6205 return std::to_string(array_index);
6211 return anchor.key();
6223 typename IteratorType::reference
value()
const
6225 return anchor.value();
6230 typename IteratorType::reference container;
6234 iteration_proxy(
typename IteratorType::reference cont)
6239 iteration_proxy_internal
begin()
6241 return iteration_proxy_internal(container.begin());
6245 iteration_proxy_internal
end()
6247 return iteration_proxy_internal(container.end());
6262 return iteration_proxy<iterator>(cont);
6270 return iteration_proxy<const_iterator>(cont);
6290 enum class token_type
6309 using lexer_char_t =
unsigned char;
6312 explicit lexer(
const string_t& s) noexcept
6313 : m_stream(
nullptr), m_buffer(s)
6315 m_content =
reinterpret_cast<const lexer_char_t*
>(s.c_str());
6316 m_start = m_cursor = m_content;
6317 m_limit = m_content + s.size();
6319 explicit lexer(std::istream* s) noexcept
6320 : m_stream(s), m_buffer()
6322 getline(*m_stream, m_buffer);
6323 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
6324 m_start = m_cursor = m_content;
6325 m_limit = m_content + m_buffer.size();
6332 lexer(
const lexer&) =
delete;
6346 static string_t to_unicode(
const std::size_t codepoint1,
6347 const std::size_t codepoint2 = 0)
6352 std::size_t codepoint = codepoint1;
6355 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6358 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6372 throw std::invalid_argument(
"missing or wrong low surrogate");
6376 if (codepoint < 0x80)
6379 result.append(1, static_cast<typename string_t::value_type>(codepoint));
6381 else if (codepoint <= 0x7ff)
6384 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
6385 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6387 else if (codepoint <= 0xffff)
6390 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
6391 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6392 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6394 else if (codepoint <= 0x10ffff)
6397 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
6398 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
6399 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6400 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6404 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
6411 static std::string token_type_name(token_type t)
6415 case token_type::uninitialized:
6416 return "<uninitialized>";
6417 case token_type::literal_true:
6418 return "true literal";
6419 case token_type::literal_false:
6420 return "false literal";
6421 case token_type::literal_null:
6422 return "null literal";
6423 case token_type::value_string:
6424 return "string literal";
6425 case token_type::value_number:
6426 return "number literal";
6427 case token_type::begin_array:
6429 case token_type::begin_object:
6431 case token_type::end_array:
6433 case token_type::end_object:
6435 case token_type::name_separator:
6437 case token_type::value_separator:
6439 case token_type::parse_error:
6440 return "<parse error>";
6441 case token_type::end_of_input:
6442 return "<end of input>";
6446 return "unknown token";
6461 token_type scan() noexcept
6472 unsigned int yyaccept = 0;
6473 static const unsigned char yybm[] =
6475 0, 0, 0, 0, 0, 0, 0, 0,
6476 0, 32, 32, 0, 0, 32, 0, 0,
6477 64, 64, 64, 64, 64, 64, 64, 64,
6478 64, 64, 64, 64, 64, 64, 64, 64,
6479 96, 64, 0, 64, 64, 64, 64, 64,
6480 64, 64, 64, 64, 64, 64, 64, 64,
6481 192, 192, 192, 192, 192, 192, 192, 192,
6482 192, 192, 64, 64, 64, 64, 64, 64,
6483 64, 64, 64, 64, 64, 64, 64, 64,
6484 64, 64, 64, 64, 64, 64, 64, 64,
6485 64, 64, 64, 64, 64, 64, 64, 64,
6486 64, 64, 64, 64, 0, 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, 64, 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,
6508 if ((m_limit - m_cursor) < 5)
6521 goto basic_json_parser_28;
6525 goto basic_json_parser_30;
6529 goto basic_json_parser_4;
6536 goto basic_json_parser_2;
6540 goto basic_json_parser_30;
6550 goto basic_json_parser_27;
6554 goto basic_json_parser_30;
6556 goto basic_json_parser_16;
6564 goto basic_json_parser_23;
6566 goto basic_json_parser_30;
6572 goto basic_json_parser_24;
6576 goto basic_json_parser_26;
6578 goto basic_json_parser_18;
6591 goto basic_json_parser_8;
6595 goto basic_json_parser_30;
6597 goto basic_json_parser_10;
6603 goto basic_json_parser_22;
6607 goto basic_json_parser_30;
6609 goto basic_json_parser_20;
6618 goto basic_json_parser_21;
6622 goto basic_json_parser_30;
6624 goto basic_json_parser_12;
6632 goto basic_json_parser_30;
6634 goto basic_json_parser_14;
6640 goto basic_json_parser_6;
6642 goto basic_json_parser_30;
6647 basic_json_parser_2:
6650 goto basic_json_parser_5;
6651 basic_json_parser_3:
6655 basic_json_parser_4:
6657 if (m_limit <= m_cursor)
6662 basic_json_parser_5:
6663 if (yybm[0 + yych] & 32)
6665 goto basic_json_parser_4;
6667 goto basic_json_parser_3;
6668 basic_json_parser_6:
6670 yych = *(m_marker = ++m_cursor);
6673 goto basic_json_parser_64;
6675 basic_json_parser_7:
6677 return token_type::parse_error;
6679 basic_json_parser_8:
6682 return token_type::begin_array;
6684 basic_json_parser_10:
6687 return token_type::end_array;
6689 basic_json_parser_12:
6692 return token_type::begin_object;
6694 basic_json_parser_14:
6697 return token_type::end_object;
6699 basic_json_parser_16:
6702 return token_type::value_separator;
6704 basic_json_parser_18:
6707 return token_type::name_separator;
6709 basic_json_parser_20:
6711 yych = *(m_marker = ++m_cursor);
6714 goto basic_json_parser_60;
6716 goto basic_json_parser_7;
6717 basic_json_parser_21:
6719 yych = *(m_marker = ++m_cursor);
6722 goto basic_json_parser_56;
6724 goto basic_json_parser_7;
6725 basic_json_parser_22:
6727 yych = *(m_marker = ++m_cursor);
6730 goto basic_json_parser_51;
6732 goto basic_json_parser_7;
6733 basic_json_parser_23:
6737 goto basic_json_parser_7;
6741 goto basic_json_parser_50;
6745 goto basic_json_parser_41;
6747 goto basic_json_parser_7;
6748 basic_json_parser_24:
6750 yych = *(m_marker = ++m_cursor);
6755 goto basic_json_parser_43;
6762 goto basic_json_parser_44;
6766 goto basic_json_parser_44;
6769 basic_json_parser_25:
6771 return token_type::value_number;
6773 basic_json_parser_26:
6775 yych = *(m_marker = ++m_cursor);
6776 goto basic_json_parser_42;
6777 basic_json_parser_27:
6779 yych = *(m_marker = ++m_cursor);
6782 goto basic_json_parser_7;
6784 goto basic_json_parser_32;
6785 basic_json_parser_28:
6788 return token_type::end_of_input;
6790 basic_json_parser_30:
6792 goto basic_json_parser_7;
6793 basic_json_parser_31:
6795 if (m_limit <= m_cursor)
6800 basic_json_parser_32:
6801 if (yybm[0 + yych] & 64)
6803 goto basic_json_parser_31;
6807 goto basic_json_parser_33;
6811 goto basic_json_parser_35;
6813 goto basic_json_parser_34;
6814 basic_json_parser_33:
6815 m_cursor = m_marker;
6818 goto basic_json_parser_7;
6822 goto basic_json_parser_25;
6824 basic_json_parser_34:
6826 if (m_limit <= m_cursor)
6837 goto basic_json_parser_31;
6841 goto basic_json_parser_33;
6843 goto basic_json_parser_31;
6851 goto basic_json_parser_33;
6853 goto basic_json_parser_31;
6859 goto basic_json_parser_31;
6861 goto basic_json_parser_33;
6871 goto basic_json_parser_31;
6875 goto basic_json_parser_31;
6877 goto basic_json_parser_33;
6885 goto basic_json_parser_31;
6887 goto basic_json_parser_33;
6893 goto basic_json_parser_31;
6897 goto basic_json_parser_37;
6899 goto basic_json_parser_33;
6903 basic_json_parser_35:
6906 return token_type::value_string;
6908 basic_json_parser_37:
6910 if (m_limit <= m_cursor)
6919 goto basic_json_parser_33;
6923 goto basic_json_parser_33;
6930 goto basic_json_parser_38;
6934 goto basic_json_parser_33;
6938 goto basic_json_parser_33;
6941 basic_json_parser_38:
6943 if (m_limit <= m_cursor)
6952 goto basic_json_parser_33;
6956 goto basic_json_parser_33;
6963 goto basic_json_parser_39;
6967 goto basic_json_parser_33;
6971 goto basic_json_parser_33;
6974 basic_json_parser_39:
6976 if (m_limit <= m_cursor)
6985 goto basic_json_parser_33;
6989 goto basic_json_parser_33;
6996 goto basic_json_parser_40;
7000 goto basic_json_parser_33;
7004 goto basic_json_parser_33;
7007 basic_json_parser_40:
7009 if (m_limit <= m_cursor)
7018 goto basic_json_parser_33;
7022 goto basic_json_parser_31;
7024 goto basic_json_parser_33;
7030 goto basic_json_parser_31;
7034 goto basic_json_parser_33;
7038 goto basic_json_parser_31;
7040 goto basic_json_parser_33;
7042 basic_json_parser_41:
7044 m_marker = ++m_cursor;
7045 if ((m_limit - m_cursor) < 3)
7050 basic_json_parser_42:
7051 if (yybm[0 + yych] & 128)
7053 goto basic_json_parser_41;
7059 goto basic_json_parser_25;
7066 goto basic_json_parser_44;
7070 goto basic_json_parser_44;
7072 goto basic_json_parser_25;
7074 basic_json_parser_43:
7078 goto basic_json_parser_33;
7082 goto basic_json_parser_48;
7084 goto basic_json_parser_33;
7085 basic_json_parser_44:
7091 goto basic_json_parser_33;
7098 goto basic_json_parser_45;
7102 goto basic_json_parser_33;
7106 goto basic_json_parser_46;
7108 goto basic_json_parser_33;
7110 basic_json_parser_45:
7114 goto basic_json_parser_33;
7118 goto basic_json_parser_33;
7120 basic_json_parser_46:
7122 if (m_limit <= m_cursor)
7129 goto basic_json_parser_25;
7133 goto basic_json_parser_46;
7135 goto basic_json_parser_25;
7136 basic_json_parser_48:
7138 m_marker = ++m_cursor;
7139 if ((m_limit - m_cursor) < 3)
7148 goto basic_json_parser_25;
7152 goto basic_json_parser_48;
7154 goto basic_json_parser_25;
7160 goto basic_json_parser_44;
7164 goto basic_json_parser_44;
7166 goto basic_json_parser_25;
7168 basic_json_parser_50:
7170 yych = *(m_marker = ++m_cursor);
7175 goto basic_json_parser_43;
7177 goto basic_json_parser_25;
7183 goto basic_json_parser_44;
7187 goto basic_json_parser_44;
7189 goto basic_json_parser_25;
7191 basic_json_parser_51:
7195 goto basic_json_parser_33;
7200 goto basic_json_parser_33;
7205 goto basic_json_parser_33;
7209 return token_type::literal_false;
7211 basic_json_parser_56:
7215 goto basic_json_parser_33;
7220 goto basic_json_parser_33;
7224 return token_type::literal_true;
7226 basic_json_parser_60:
7230 goto basic_json_parser_33;
7235 goto basic_json_parser_33;
7239 return token_type::literal_null;
7241 basic_json_parser_64:
7245 goto basic_json_parser_33;
7257 void yyfill() noexcept
7259 if (not m_stream or not * m_stream)
7264 const ssize_t offset_start = m_start - m_content;
7265 const ssize_t offset_marker = m_marker - m_start;
7266 const ssize_t offset_cursor = m_cursor - m_start;
7268 m_buffer.erase(0, static_cast<size_t>(offset_start));
7270 std::getline(*m_stream, line);
7271 m_buffer +=
"\n" + line;
7273 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
7274 m_start = m_content;
7275 m_marker = m_start + offset_marker;
7276 m_cursor = m_start + offset_cursor;
7277 m_limit = m_start + m_buffer.size() - 1;
7281 string_t get_token() const noexcept
7283 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7284 static_cast<size_t>(m_cursor - m_start));
7311 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7314 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7370 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7371 4).c_str(),
nullptr, 16);
7374 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7377 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
7379 throw std::invalid_argument(
"missing low surrogate");
7383 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7384 (i + 7), 4).c_str(),
nullptr, 16);
7385 result += to_unicode(codepoint, codepoint2);
7392 result += to_unicode(codepoint);
7404 result.append(1, static_cast<typename string_t::value_type>(*i));
7428 long double get_number()
const
7431 typename string_t::value_type* endptr;
7432 const auto float_val = std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start),
7437 return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
7442 std::istream* m_stream;
7446 const lexer_char_t* m_content =
nullptr;
7448 const lexer_char_t* m_start =
nullptr;
7450 const lexer_char_t* m_marker =
nullptr;
7452 const lexer_char_t* m_cursor =
nullptr;
7454 const lexer_char_t* m_limit =
nullptr;
7467 : callback(cb), m_lexer(s)
7475 : callback(cb), m_lexer(&_is)
7484 basic_json result = parse_internal(
true);
7486 expect(lexer::token_type::end_of_input);
7490 return result.is_discarded() ?
basic_json() : result;
7495 basic_json parse_internal(
bool keep)
7501 case lexer::token_type::begin_object:
7514 if (last_token == lexer::token_type::end_object)
7525 unexpect(lexer::token_type::value_separator);
7531 if (last_token == lexer::token_type::value_separator)
7537 expect(lexer::token_type::value_string);
7538 const auto key = m_lexer.get_string();
7540 bool keep_tag =
false;
7556 expect(lexer::token_type::name_separator);
7560 auto value = parse_internal(keep);
7561 if (keep and keep_tag and not
value.is_discarded())
7563 result[key] = std::move(
value);
7566 while (last_token == lexer::token_type::value_separator);
7569 expect(lexer::token_type::end_object);
7579 case lexer::token_type::begin_array:
7592 if (last_token == lexer::token_type::end_array)
7603 unexpect(lexer::token_type::value_separator);
7609 if (last_token == lexer::token_type::value_separator)
7615 auto value = parse_internal(keep);
7616 if (keep and not
value.is_discarded())
7618 result.push_back(std::move(
value));
7621 while (last_token == lexer::token_type::value_separator);
7624 expect(lexer::token_type::end_array);
7634 case lexer::token_type::literal_null:
7641 case lexer::token_type::value_string:
7643 const auto s = m_lexer.get_string();
7649 case lexer::token_type::literal_true:
7653 result.m_value =
true;
7657 case lexer::token_type::literal_false:
7661 result.m_value =
false;
7665 case lexer::token_type::value_number:
7667 auto float_val = m_lexer.get_number();
7671 if (std::isnan(float_val))
7673 throw std::invalid_argument(std::string(
"parse error - ") +
7674 m_lexer.get_token() +
" is not a number");
7681 if (approx(float_val, static_cast<long double>(int_val)))
7685 result.m_value = int_val;
7699 unexpect(last_token);
7711 typename lexer::token_type get_token()
7713 last_token = m_lexer.scan();
7717 void expect(
typename lexer::token_type t)
const
7719 if (t != last_token)
7721 std::string error_msg =
"parse error - unexpected \'";
7722 error_msg += m_lexer.get_token();
7723 error_msg +=
"\' (" + lexer::token_type_name(last_token);
7724 error_msg +=
"); expected " + lexer::token_type_name(t);
7725 throw std::invalid_argument(error_msg);
7729 void unexpect(
typename lexer::token_type t)
const
7731 if (t == last_token)
7733 std::string error_msg =
"parse error - unexpected \'";
7734 error_msg += m_lexer.get_token();
7735 error_msg +=
"\' (";
7736 error_msg += lexer::token_type_name(last_token) +
")";
7737 throw std::invalid_argument(error_msg);
7747 typename lexer::token_type last_token = lexer::token_type::uninitialized;
7785 is_nothrow_move_constructible<nlohmann::json>::value and
7786 is_nothrow_move_assignable<nlohmann::json>::value
7804 const auto& h = hash<nlohmann::json::string_t>();
7822 inline nlohmann::json operator "" _json(
const char* s, std::size_t)
7825 (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