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 * ();
6166 basic_json& container;
6168 using json_iterator = decltype(std::begin(container));
6171 class iterator_wrapper_internal
6175 json_iterator anchor;
6177 size_t array_index = 0;
6181 iterator_wrapper_internal(json_iterator i) : anchor(i)
6185 iterator_wrapper_internal& operator*()
6191 iterator_wrapper_internal& operator++()
6200 bool operator!= (
const iterator_wrapper_internal& o)
6202 return anchor != o.anchor;
6208 switch (anchor.m_object->type())
6213 return std::to_string(array_index);
6219 return anchor.key();
6231 typename json_iterator::reference
value()
const
6233 return anchor.value();
6246 return iterator_wrapper_internal(container.
begin());
6250 iterator_wrapper_internal
end()
6252 return iterator_wrapper_internal(container.
end());
6272 enum class token_type
6291 using lexer_char_t =
unsigned char;
6294 explicit lexer(
const string_t& s) noexcept
6295 : m_stream(
nullptr), m_buffer(s)
6297 m_content =
reinterpret_cast<const lexer_char_t*
>(s.c_str());
6298 m_start = m_cursor = m_content;
6299 m_limit = m_content + s.size();
6301 explicit lexer(std::istream* s) noexcept
6302 : m_stream(s), m_buffer()
6304 getline(*m_stream, m_buffer);
6305 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
6306 m_start = m_cursor = m_content;
6307 m_limit = m_content + m_buffer.size();
6314 lexer(
const lexer&) =
delete;
6328 static string_t to_unicode(
const std::size_t codepoint1,
6329 const std::size_t codepoint2 = 0)
6334 std::size_t codepoint = codepoint1;
6337 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6340 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6354 throw std::invalid_argument(
"missing or wrong low surrogate");
6358 if (codepoint < 0x80)
6361 result.append(1, static_cast<typename string_t::value_type>(codepoint));
6363 else if (codepoint <= 0x7ff)
6366 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
6367 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6369 else if (codepoint <= 0xffff)
6372 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
6373 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6374 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6376 else if (codepoint <= 0x10ffff)
6379 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
6380 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
6381 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6382 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6386 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
6393 static std::string token_type_name(token_type t)
6397 case token_type::uninitialized:
6398 return "<uninitialized>";
6399 case token_type::literal_true:
6400 return "true literal";
6401 case token_type::literal_false:
6402 return "false literal";
6403 case token_type::literal_null:
6404 return "null literal";
6405 case token_type::value_string:
6406 return "string literal";
6407 case token_type::value_number:
6408 return "number literal";
6409 case token_type::begin_array:
6411 case token_type::begin_object:
6413 case token_type::end_array:
6415 case token_type::end_object:
6417 case token_type::name_separator:
6419 case token_type::value_separator:
6421 case token_type::parse_error:
6422 return "<parse error>";
6423 case token_type::end_of_input:
6424 return "<end of input>";
6428 return "unknown token";
6443 token_type scan() noexcept
6454 unsigned int yyaccept = 0;
6455 static const unsigned char yybm[] =
6457 0, 0, 0, 0, 0, 0, 0, 0,
6458 0, 32, 32, 0, 0, 32, 0, 0,
6459 64, 64, 64, 64, 64, 64, 64, 64,
6460 64, 64, 64, 64, 64, 64, 64, 64,
6461 96, 64, 0, 64, 64, 64, 64, 64,
6462 64, 64, 64, 64, 64, 64, 64, 64,
6463 192, 192, 192, 192, 192, 192, 192, 192,
6464 192, 192, 64, 64, 64, 64, 64, 64,
6465 64, 64, 64, 64, 64, 64, 64, 64,
6466 64, 64, 64, 64, 64, 64, 64, 64,
6467 64, 64, 64, 64, 64, 64, 64, 64,
6468 64, 64, 64, 64, 0, 64, 64, 64,
6469 64, 64, 64, 64, 64, 64, 64, 64,
6470 64, 64, 64, 64, 64, 64, 64, 64,
6471 64, 64, 64, 64, 64, 64, 64, 64,
6472 64, 64, 64, 64, 64, 64, 64, 64,
6473 64, 64, 64, 64, 64, 64, 64, 64,
6474 64, 64, 64, 64, 64, 64, 64, 64,
6475 64, 64, 64, 64, 64, 64, 64, 64,
6476 64, 64, 64, 64, 64, 64, 64, 64,
6477 64, 64, 64, 64, 64, 64, 64, 64,
6478 64, 64, 64, 64, 64, 64, 64, 64,
6479 64, 64, 64, 64, 64, 64, 64, 64,
6480 64, 64, 64, 64, 64, 64, 64, 64,
6481 64, 64, 64, 64, 64, 64, 64, 64,
6482 64, 64, 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, 64, 64, 64, 64,
6487 64, 64, 64, 64, 64, 64, 64, 64,
6488 64, 64, 64, 64, 64, 64, 64, 64,
6490 if ((m_limit - m_cursor) < 5)
6503 goto basic_json_parser_28;
6507 goto basic_json_parser_30;
6511 goto basic_json_parser_4;
6518 goto basic_json_parser_2;
6522 goto basic_json_parser_30;
6532 goto basic_json_parser_27;
6536 goto basic_json_parser_30;
6538 goto basic_json_parser_16;
6546 goto basic_json_parser_23;
6548 goto basic_json_parser_30;
6554 goto basic_json_parser_24;
6558 goto basic_json_parser_26;
6560 goto basic_json_parser_18;
6573 goto basic_json_parser_8;
6577 goto basic_json_parser_30;
6579 goto basic_json_parser_10;
6585 goto basic_json_parser_22;
6589 goto basic_json_parser_30;
6591 goto basic_json_parser_20;
6600 goto basic_json_parser_21;
6604 goto basic_json_parser_30;
6606 goto basic_json_parser_12;
6614 goto basic_json_parser_30;
6616 goto basic_json_parser_14;
6622 goto basic_json_parser_6;
6624 goto basic_json_parser_30;
6629 basic_json_parser_2:
6632 goto basic_json_parser_5;
6633 basic_json_parser_3:
6637 basic_json_parser_4:
6639 if (m_limit <= m_cursor)
6644 basic_json_parser_5:
6645 if (yybm[0 + yych] & 32)
6647 goto basic_json_parser_4;
6649 goto basic_json_parser_3;
6650 basic_json_parser_6:
6652 yych = *(m_marker = ++m_cursor);
6655 goto basic_json_parser_64;
6657 basic_json_parser_7:
6659 return token_type::parse_error;
6661 basic_json_parser_8:
6664 return token_type::begin_array;
6666 basic_json_parser_10:
6669 return token_type::end_array;
6671 basic_json_parser_12:
6674 return token_type::begin_object;
6676 basic_json_parser_14:
6679 return token_type::end_object;
6681 basic_json_parser_16:
6684 return token_type::value_separator;
6686 basic_json_parser_18:
6689 return token_type::name_separator;
6691 basic_json_parser_20:
6693 yych = *(m_marker = ++m_cursor);
6696 goto basic_json_parser_60;
6698 goto basic_json_parser_7;
6699 basic_json_parser_21:
6701 yych = *(m_marker = ++m_cursor);
6704 goto basic_json_parser_56;
6706 goto basic_json_parser_7;
6707 basic_json_parser_22:
6709 yych = *(m_marker = ++m_cursor);
6712 goto basic_json_parser_51;
6714 goto basic_json_parser_7;
6715 basic_json_parser_23:
6719 goto basic_json_parser_7;
6723 goto basic_json_parser_50;
6727 goto basic_json_parser_41;
6729 goto basic_json_parser_7;
6730 basic_json_parser_24:
6732 yych = *(m_marker = ++m_cursor);
6737 goto basic_json_parser_43;
6744 goto basic_json_parser_44;
6748 goto basic_json_parser_44;
6751 basic_json_parser_25:
6753 return token_type::value_number;
6755 basic_json_parser_26:
6757 yych = *(m_marker = ++m_cursor);
6758 goto basic_json_parser_42;
6759 basic_json_parser_27:
6761 yych = *(m_marker = ++m_cursor);
6764 goto basic_json_parser_7;
6766 goto basic_json_parser_32;
6767 basic_json_parser_28:
6770 return token_type::end_of_input;
6772 basic_json_parser_30:
6774 goto basic_json_parser_7;
6775 basic_json_parser_31:
6777 if (m_limit <= m_cursor)
6782 basic_json_parser_32:
6783 if (yybm[0 + yych] & 64)
6785 goto basic_json_parser_31;
6789 goto basic_json_parser_33;
6793 goto basic_json_parser_35;
6795 goto basic_json_parser_34;
6796 basic_json_parser_33:
6797 m_cursor = m_marker;
6800 goto basic_json_parser_7;
6804 goto basic_json_parser_25;
6806 basic_json_parser_34:
6808 if (m_limit <= m_cursor)
6819 goto basic_json_parser_31;
6823 goto basic_json_parser_33;
6825 goto basic_json_parser_31;
6833 goto basic_json_parser_33;
6835 goto basic_json_parser_31;
6841 goto basic_json_parser_31;
6843 goto basic_json_parser_33;
6853 goto basic_json_parser_31;
6857 goto basic_json_parser_31;
6859 goto basic_json_parser_33;
6867 goto basic_json_parser_31;
6869 goto basic_json_parser_33;
6875 goto basic_json_parser_31;
6879 goto basic_json_parser_37;
6881 goto basic_json_parser_33;
6885 basic_json_parser_35:
6888 return token_type::value_string;
6890 basic_json_parser_37:
6892 if (m_limit <= m_cursor)
6901 goto basic_json_parser_33;
6905 goto basic_json_parser_33;
6912 goto basic_json_parser_38;
6916 goto basic_json_parser_33;
6920 goto basic_json_parser_33;
6923 basic_json_parser_38:
6925 if (m_limit <= m_cursor)
6934 goto basic_json_parser_33;
6938 goto basic_json_parser_33;
6945 goto basic_json_parser_39;
6949 goto basic_json_parser_33;
6953 goto basic_json_parser_33;
6956 basic_json_parser_39:
6958 if (m_limit <= m_cursor)
6967 goto basic_json_parser_33;
6971 goto basic_json_parser_33;
6978 goto basic_json_parser_40;
6982 goto basic_json_parser_33;
6986 goto basic_json_parser_33;
6989 basic_json_parser_40:
6991 if (m_limit <= m_cursor)
7000 goto basic_json_parser_33;
7004 goto basic_json_parser_31;
7006 goto basic_json_parser_33;
7012 goto basic_json_parser_31;
7016 goto basic_json_parser_33;
7020 goto basic_json_parser_31;
7022 goto basic_json_parser_33;
7024 basic_json_parser_41:
7026 m_marker = ++m_cursor;
7027 if ((m_limit - m_cursor) < 3)
7032 basic_json_parser_42:
7033 if (yybm[0 + yych] & 128)
7035 goto basic_json_parser_41;
7041 goto basic_json_parser_25;
7048 goto basic_json_parser_44;
7052 goto basic_json_parser_44;
7054 goto basic_json_parser_25;
7056 basic_json_parser_43:
7060 goto basic_json_parser_33;
7064 goto basic_json_parser_48;
7066 goto basic_json_parser_33;
7067 basic_json_parser_44:
7073 goto basic_json_parser_33;
7080 goto basic_json_parser_45;
7084 goto basic_json_parser_33;
7088 goto basic_json_parser_46;
7090 goto basic_json_parser_33;
7092 basic_json_parser_45:
7096 goto basic_json_parser_33;
7100 goto basic_json_parser_33;
7102 basic_json_parser_46:
7104 if (m_limit <= m_cursor)
7111 goto basic_json_parser_25;
7115 goto basic_json_parser_46;
7117 goto basic_json_parser_25;
7118 basic_json_parser_48:
7120 m_marker = ++m_cursor;
7121 if ((m_limit - m_cursor) < 3)
7130 goto basic_json_parser_25;
7134 goto basic_json_parser_48;
7136 goto basic_json_parser_25;
7142 goto basic_json_parser_44;
7146 goto basic_json_parser_44;
7148 goto basic_json_parser_25;
7150 basic_json_parser_50:
7152 yych = *(m_marker = ++m_cursor);
7157 goto basic_json_parser_43;
7159 goto basic_json_parser_25;
7165 goto basic_json_parser_44;
7169 goto basic_json_parser_44;
7171 goto basic_json_parser_25;
7173 basic_json_parser_51:
7177 goto basic_json_parser_33;
7182 goto basic_json_parser_33;
7187 goto basic_json_parser_33;
7191 return token_type::literal_false;
7193 basic_json_parser_56:
7197 goto basic_json_parser_33;
7202 goto basic_json_parser_33;
7206 return token_type::literal_true;
7208 basic_json_parser_60:
7212 goto basic_json_parser_33;
7217 goto basic_json_parser_33;
7221 return token_type::literal_null;
7223 basic_json_parser_64:
7227 goto basic_json_parser_33;
7239 void yyfill() noexcept
7241 if (not m_stream or not * m_stream)
7246 const ssize_t offset_start = m_start - m_content;
7247 const ssize_t offset_marker = m_marker - m_start;
7248 const ssize_t offset_cursor = m_cursor - m_start;
7250 m_buffer.erase(0, static_cast<size_t>(offset_start));
7252 std::getline(*m_stream, line);
7253 m_buffer +=
"\n" + line;
7255 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
7256 m_start = m_content;
7257 m_marker = m_start + offset_marker;
7258 m_cursor = m_start + offset_cursor;
7259 m_limit = m_start + m_buffer.size() - 1;
7263 string_t get_token() const noexcept
7265 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7266 static_cast<size_t>(m_cursor - m_start));
7293 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7296 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7352 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7353 4).c_str(),
nullptr, 16);
7356 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7359 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
7361 throw std::invalid_argument(
"missing low surrogate");
7365 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7366 (i + 7), 4).c_str(),
nullptr, 16);
7367 result += to_unicode(codepoint, codepoint2);
7374 result += to_unicode(codepoint);
7386 result.append(1, static_cast<typename string_t::value_type>(*i));
7410 long double get_number()
const
7413 typename string_t::value_type* endptr;
7414 const auto float_val = std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start),
7419 return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
7424 std::istream* m_stream;
7428 const lexer_char_t* m_content =
nullptr;
7430 const lexer_char_t* m_start =
nullptr;
7432 const lexer_char_t* m_marker =
nullptr;
7434 const lexer_char_t* m_cursor =
nullptr;
7436 const lexer_char_t* m_limit =
nullptr;
7449 : callback(cb), m_lexer(s)
7457 : callback(cb), m_lexer(&_is)
7466 basic_json result = parse_internal(
true);
7468 expect(lexer::token_type::end_of_input);
7472 return result.is_discarded() ?
basic_json() : result;
7477 basic_json parse_internal(
bool keep)
7483 case lexer::token_type::begin_object:
7496 if (last_token == lexer::token_type::end_object)
7507 unexpect(lexer::token_type::value_separator);
7513 if (last_token == lexer::token_type::value_separator)
7519 expect(lexer::token_type::value_string);
7520 const auto key = m_lexer.get_string();
7522 bool keep_tag =
false;
7538 expect(lexer::token_type::name_separator);
7542 auto value = parse_internal(keep);
7543 if (keep and keep_tag and not
value.is_discarded())
7545 result[key] = std::move(
value);
7548 while (last_token == lexer::token_type::value_separator);
7551 expect(lexer::token_type::end_object);
7561 case lexer::token_type::begin_array:
7574 if (last_token == lexer::token_type::end_array)
7585 unexpect(lexer::token_type::value_separator);
7591 if (last_token == lexer::token_type::value_separator)
7597 auto value = parse_internal(keep);
7598 if (keep and not
value.is_discarded())
7600 result.push_back(std::move(
value));
7603 while (last_token == lexer::token_type::value_separator);
7606 expect(lexer::token_type::end_array);
7616 case lexer::token_type::literal_null:
7623 case lexer::token_type::value_string:
7625 const auto s = m_lexer.get_string();
7631 case lexer::token_type::literal_true:
7635 result.m_value =
true;
7639 case lexer::token_type::literal_false:
7643 result.m_value =
false;
7647 case lexer::token_type::value_number:
7649 auto float_val = m_lexer.get_number();
7653 if (std::isnan(float_val))
7655 throw std::invalid_argument(std::string(
"parse error - ") +
7656 m_lexer.get_token() +
" is not a number");
7663 if (approx(float_val, static_cast<long double>(int_val)))
7667 result.m_value = int_val;
7681 unexpect(last_token);
7693 typename lexer::token_type get_token()
7695 last_token = m_lexer.scan();
7699 void expect(
typename lexer::token_type t)
const
7701 if (t != last_token)
7703 std::string error_msg =
"parse error - unexpected \'";
7704 error_msg += m_lexer.get_token();
7705 error_msg +=
"\' (" + lexer::token_type_name(last_token);
7706 error_msg +=
"); expected " + lexer::token_type_name(t);
7707 throw std::invalid_argument(error_msg);
7711 void unexpect(
typename lexer::token_type t)
const
7713 if (t == last_token)
7715 std::string error_msg =
"parse error - unexpected \'";
7716 error_msg += m_lexer.get_token();
7717 error_msg +=
"\' (";
7718 error_msg += lexer::token_type_name(last_token) +
")";
7719 throw std::invalid_argument(error_msg);
7729 typename lexer::token_type last_token = lexer::token_type::uninitialized;
7767 is_nothrow_move_constructible<nlohmann::json>::value and
7768 is_nothrow_move_assignable<nlohmann::json>::value
7786 const auto& h = hash<nlohmann::json::string_t>();
7804 inline nlohmann::json operator "" _json(
const char* s, std::size_t)
7807 (const_cast<char*>(s)));
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
iterator_wrapper(basic_json &cont)
construct iterator wrapper from a 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)
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
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
iterator_wrapper_internal end()
return iterator end (needed for range-based for)
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
iterator_wrapper_internal begin()
return iterator begin (needed for range-based for)
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
wrapper to access iterator member functions in range-based for