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>();
2621 return m_value.array->at(idx);
2625 throw std::domain_error(
"cannot use at() with " + type_name());
2655 return m_value.array->at(idx);
2659 throw std::domain_error(
"cannot use at() with " + type_name());
2693 return m_value.object->at(key);
2697 throw std::domain_error(
"cannot use at() with " + type_name());
2731 return m_value.object->at(key);
2735 throw std::domain_error(
"cannot use at() with " + type_name());
2769 m_value.array = create<array_t>();
2775 for (
size_t i = m_value.array->size(); i <= idx; ++i)
2780 return m_value.array->operator[](idx);
2784 throw std::domain_error(
"cannot use operator[] with " + type_name());
2811 return m_value.array->operator[](idx);
2815 throw std::domain_error(
"cannot use operator[] with " + type_name());
2851 m_value.object = create<object_t>();
2857 return m_value.object->operator[](key);
2861 throw std::domain_error(
"cannot use operator[] with " + type_name());
2893 template<
typename T, std::
size_t n>
2906 return m_value.object->operator[](key);
2910 throw std::domain_error(
"cannot use operator[] with " + type_name());
2961 template <
class ValueType,
typename
2963 std::is_convertible<basic_json_t, ValueType>::value
2965 ValueType
value(
const typename object_t::key_type& key, ValueType default_value)
const
2971 const auto it =
find(key);
2978 return default_value;
2983 throw std::domain_error(
"cannot use value() with " + type_name());
2991 string_t value(
const typename object_t::key_type& key,
const char* default_value)
const
3109 template <
class InteratorType,
typename
3111 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3112 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3118 if (
this != pos.m_object)
3120 throw std::domain_error(
"iterator does not fit current value");
3123 InteratorType result =
end();
3132 if (not pos.m_it.primitive_iterator.is_begin())
3134 throw std::out_of_range(
"iterator out of range");
3139 delete m_value.string;
3140 m_value.string =
nullptr;
3149 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3155 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3161 throw std::domain_error(
"cannot use erase() with " + type_name());
3210 template <
class InteratorType,
typename
3212 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3213 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3216 InteratorType
erase(InteratorType first, InteratorType last)
3219 if (
this != first.m_object or
this != last.m_object)
3221 throw std::domain_error(
"iterators do not fit current value");
3224 InteratorType result =
end();
3233 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3235 throw std::out_of_range(
"iterators out of range");
3240 delete m_value.string;
3241 m_value.string =
nullptr;
3250 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3251 last.m_it.object_iterator);
3257 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3258 last.m_it.array_iterator);
3264 throw std::domain_error(
"cannot use erase with " + type_name());
3301 return m_value.object->erase(key);
3305 throw std::domain_error(
"cannot use erase() with " + type_name());
3338 throw std::out_of_range(
"index out of range");
3341 m_value.array->erase(m_value.array->begin() +
static_cast<difference_type>(idx));
3345 throw std::domain_error(
"cannot use erase() with " + type_name());
3368 auto result =
end();
3372 result.m_it.object_iterator = m_value.object->find(key);
3384 auto result =
cend();
3388 result.m_it.object_iterator = m_value.object->find(key);
3415 return is_object() ? m_value.object->count(key) : 0;
3704 return m_value.array->empty();
3709 return m_value.object->empty();
3761 return m_value.array->size();
3766 return m_value.object->size();
3815 return m_value.array->max_size();
3820 return m_value.object->max_size();
3872 m_value.number_integer = 0;
3878 m_value.number_float = 0.0;
3884 m_value.boolean =
false;
3890 m_value.string->clear();
3896 m_value.array->clear();
3902 m_value.object->clear();
3937 throw std::domain_error(
"cannot use push_back() with " + type_name());
3948 m_value.array->push_back(std::move(val));
3972 throw std::domain_error(
"cannot use push_back() with " + type_name());
3983 m_value.array->push_back(val);
4021 throw std::domain_error(
"cannot use push_back() with " + type_name());
4032 m_value.object->insert(val);
4071 if (pos.m_object !=
this)
4073 throw std::domain_error(
"iterator does not fit current value");
4078 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4083 throw std::domain_error(
"cannot use insert() with " + type_name());
4124 if (pos.m_object !=
this)
4126 throw std::domain_error(
"iterator does not fit current value");
4131 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4136 throw std::domain_error(
"cannot use insert() with " + type_name());
4171 throw std::domain_error(
"cannot use insert() with " + type_name());
4175 if (pos.m_object !=
this)
4177 throw std::domain_error(
"iterator does not fit current value");
4180 if (first.m_object != last.m_object)
4182 throw std::domain_error(
"iterators do not fit");
4185 if (first.m_object ==
this or last.m_object ==
this)
4187 throw std::domain_error(
"passed iterators may not belong to container");
4192 result.m_it.array_iterator = m_value.array->insert(
4193 pos.m_it.array_iterator,
4194 first.m_it.array_iterator,
4195 last.m_it.array_iterator);
4225 throw std::domain_error(
"cannot use insert() with " + type_name());
4229 if (pos.m_object !=
this)
4231 throw std::domain_error(
"iterator does not fit current value");
4236 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4258 std::is_nothrow_move_constructible<value_t>::value and
4259 std::is_nothrow_move_assignable<value_t>::value and
4260 std::is_nothrow_move_constructible<json_value>::value and
4261 std::is_nothrow_move_assignable<json_value>::value
4264 std::swap(m_type, other.m_type);
4265 std::swap(m_value, other.m_value);
4292 std::swap(*(m_value.array), other);
4296 throw std::domain_error(
"cannot use swap() with " + type_name());
4324 std::swap(*(m_value.object), other);
4328 throw std::domain_error(
"cannot use swap() with " + type_name());
4356 std::swap(*(m_value.string), other);
4360 throw std::domain_error(
"cannot use swap() with " + type_name());
4386 static constexpr std::array<uint8_t, 7> order = {{
4403 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
4432 const auto lhs_type = lhs.type();
4433 const auto rhs_type = rhs.type();
4435 if (lhs_type == rhs_type)
4440 return *lhs.m_value.array == *rhs.m_value.array;
4442 return *lhs.m_value.object == *rhs.m_value.object;
4446 return *lhs.m_value.string == *rhs.m_value.string;
4448 return lhs.m_value.boolean == rhs.m_value.boolean;
4450 return lhs.m_value.number_integer == rhs.m_value.number_integer;
4452 return approx(lhs.m_value.number_float, rhs.m_value.number_float);
4459 return approx(static_cast<number_float_t>(lhs.m_value.number_integer),
4460 rhs.m_value.number_float);
4464 return approx(lhs.m_value.number_float,
4465 static_cast<number_float_t>(rhs.m_value.number_integer));
4520 return not (lhs == rhs);
4552 return not v.is_null();
4581 const auto lhs_type = lhs.type();
4582 const auto rhs_type = rhs.type();
4584 if (lhs_type == rhs_type)
4589 return *lhs.m_value.array < *rhs.m_value.array;
4591 return *lhs.m_value.object < *rhs.m_value.object;
4595 return *lhs.m_value.string < *rhs.m_value.string;
4597 return lhs.m_value.boolean < rhs.m_value.boolean;
4599 return lhs.m_value.number_integer < rhs.m_value.number_integer;
4601 return lhs.m_value.number_float < rhs.m_value.number_float;
4609 rhs.m_value.number_float;
4613 return lhs.m_value.number_float <
4642 return not (rhs < lhs);
4664 return not (lhs <= rhs);
4686 return not (lhs < rhs);
4721 friend std::ostream&
operator<<(std::ostream& o,
const basic_json& j)
4724 const bool pretty_print = (o.width() > 0);
4725 const auto indentation = (pretty_print ? o.width() : 0);
4731 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
4739 friend std::ostream&
operator>>(
const basic_json& j, std::ostream& o)
4780 return parser(s, cb).
parse();
4809 return parser(i, cb).
parse();
4817 return parser(i, cb).
parse();
4845 j = parser(i).
parse();
4855 j = parser(i).
parse();
4897 static std::size_t extra_space(
const string_t& s) noexcept
4899 std::size_t result = 0;
4901 for (
const auto& c : s)
4920 if (c >= 0x00 and c <= 0x1f)
4948 const auto space = extra_space(s);
4955 string_t result(s.size() + space,
'\\');
4956 std::size_t pos = 0;
4958 for (
const auto& c : s)
4965 result[pos + 1] =
'"';
4981 result[pos + 1] =
'b';
4989 result[pos + 1] =
'f';
4997 result[pos + 1] =
'n';
5005 result[pos + 1] =
'r';
5013 result[pos + 1] =
't';
5020 if (c >= 0x00 and c <= 0x1f)
5023 auto hexify = [](
const char v) ->
char
5025 return (v < 10) ? (
'0' + v) : (
'a' + v - 10);
5030 {
'u',
'0',
'0', hexify(c >> 4), hexify(c & 0x0f)
5068 void dump(std::ostream& o,
5069 const bool pretty_print,
5070 const unsigned int indent_step,
5071 const unsigned int current_indent = 0)
const
5074 unsigned int new_indent = current_indent;
5080 if (m_value.object->empty())
5091 new_indent += indent_step;
5095 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5097 if (i != m_value.object->cbegin())
5099 o << (pretty_print ?
",\n" :
",");
5101 o <<
string_t(new_indent,
' ') <<
"\""
5102 << escape_string(i->first) <<
"\":"
5103 << (pretty_print ?
" " :
"");
5104 i->second.dump(o, pretty_print, indent_step, new_indent);
5110 new_indent -= indent_step;
5114 o <<
string_t(new_indent,
' ') +
"}";
5120 if (m_value.array->empty())
5131 new_indent += indent_step;
5135 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5137 if (i != m_value.array->cbegin())
5139 o << (pretty_print ?
",\n" :
",");
5142 i->dump(o, pretty_print, indent_step, new_indent);
5148 new_indent -= indent_step;
5152 o <<
string_t(new_indent,
' ') <<
"]";
5158 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
5164 o << (m_value.boolean ?
"true" :
"false");
5170 o << m_value.number_integer;
5179 o << std::setprecision(std::numeric_limits<number_float_t>::digits10) << m_value.number_float;
5206 json_value m_value = {};
5223 class primitive_iterator_t
5239 bool is_begin()
const
5241 return (m_it == begin_value);
5247 return (m_it == end_value);
5267 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5277 struct internal_iterator
5280 typename object_t::iterator object_iterator;
5282 typename array_t::iterator array_iterator;
5284 primitive_iterator_t primitive_iterator;
5288 : object_iterator(), array_iterator(), primitive_iterator()
5306 class const_iterator :
public std::iterator<std::random_access_iterator_tag, const basic_json>
5309 friend class basic_json;
5329 switch (m_object->m_type)
5333 m_it.object_iterator =
typename object_t::iterator();
5339 m_it.array_iterator =
typename array_t::iterator();
5345 m_it.primitive_iterator = primitive_iterator_t();
5354 switch (m_object->m_type)
5358 m_it.object_iterator = other.m_it.object_iterator;
5364 m_it.array_iterator = other.m_it.array_iterator;
5370 m_it.primitive_iterator = other.m_it.primitive_iterator;
5378 : m_object(other.m_object), m_it(other.m_it)
5383 std::is_nothrow_move_constructible<pointer>::value and
5384 std::is_nothrow_move_assignable<pointer>::value and
5385 std::is_nothrow_move_constructible<internal_iterator>::value and
5386 std::is_nothrow_move_assignable<internal_iterator>::value
5389 std::swap(m_object, other.m_object);
5390 std::swap(m_it, other.m_it);
5398 switch (m_object->m_type)
5402 m_it.object_iterator = m_object->m_value.object->begin();
5408 m_it.array_iterator = m_object->m_value.array->begin();
5415 m_it.primitive_iterator.set_end();
5421 m_it.primitive_iterator.set_begin();
5430 switch (m_object->m_type)
5434 m_it.object_iterator = m_object->m_value.object->end();
5440 m_it.array_iterator = m_object->m_value.array->end();
5446 m_it.primitive_iterator.set_end();
5456 switch (m_object->m_type)
5460 return m_it.object_iterator->second;
5465 return *m_it.array_iterator;
5470 throw std::out_of_range(
"cannot get value");
5475 if (m_it.primitive_iterator.is_begin())
5481 throw std::out_of_range(
"cannot get value");
5490 switch (m_object->m_type)
5494 return &(m_it.object_iterator->second);
5499 return &*m_it.array_iterator;
5504 if (m_it.primitive_iterator.is_begin())
5510 throw std::out_of_range(
"cannot get value");
5519 auto result = *
this;
5527 switch (m_object->m_type)
5531 ++m_it.object_iterator;
5537 ++m_it.array_iterator;
5543 ++m_it.primitive_iterator;
5554 auto result = *
this;
5562 switch (m_object->m_type)
5566 --m_it.object_iterator;
5572 --m_it.array_iterator;
5578 --m_it.primitive_iterator;
5590 if (m_object != other.m_object)
5592 throw std::domain_error(
"cannot compare iterators of different containers");
5595 switch (m_object->m_type)
5599 return (m_it.object_iterator == other.m_it.object_iterator);
5604 return (m_it.array_iterator == other.m_it.array_iterator);
5609 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
5624 if (m_object != other.m_object)
5626 throw std::domain_error(
"cannot compare iterators of different containers");
5629 switch (m_object->m_type)
5633 throw std::domain_error(
"cannot use operator< for object iterators");
5638 return (m_it.array_iterator < other.m_it.array_iterator);
5643 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
5651 return not other.operator < (*this);
5669 switch (m_object->m_type)
5673 throw std::domain_error(
"cannot use operator+= for object iterators");
5678 m_it.array_iterator += i;
5684 m_it.primitive_iterator += i;
5701 auto result = *
this;
5709 auto result = *
this;
5717 switch (m_object->m_type)
5721 throw std::domain_error(
"cannot use operator- for object iterators");
5726 return m_it.array_iterator - other.m_it.array_iterator;
5731 return m_it.primitive_iterator - other.m_it.primitive_iterator;
5739 switch (m_object->m_type)
5743 throw std::domain_error(
"cannot use operator[] for object iterators");
5748 return *(m_it.array_iterator + n);
5753 throw std::out_of_range(
"cannot get value");
5758 if (m_it.primitive_iterator == -n)
5764 throw std::out_of_range(
"cannot get value");
5771 typename object_t::key_type
key()
const
5773 if (m_object->is_object())
5775 return m_it.object_iterator->first;
5779 throw std::domain_error(
"cannot use key() for non-object iterators");
5793 internal_iterator m_it = internal_iterator();
5829 std::is_nothrow_move_constructible<pointer>::value and
5830 std::is_nothrow_move_assignable<pointer>::value and
5831 std::is_nothrow_move_constructible<internal_iterator>::value and
5832 std::is_nothrow_move_assignable<internal_iterator>::value
5898 auto result = *
this;
5906 auto result = *
this;
5946 template<
typename Base>
5947 class json_reverse_iterator :
public std::reverse_iterator<Base>
5965 return base_iterator::operator++(1);
5971 base_iterator::operator++();
5978 return base_iterator::operator--(1);
5984 base_iterator::operator--();
5991 base_iterator::operator+=(i);
5998 auto result = *
this;
6006 auto result = *
this;
6014 return this->base() - other.base();
6024 typename object_t::key_type
key()
const
6026 auto it = --this->base();
6033 auto it = --this->base();
6034 return it.operator * ();
6049 basic_json& container;
6051 using json_iterator = decltype(std::begin(container));
6054 class iterator_wrapper_internal
6058 json_iterator anchor;
6060 size_t array_index = 0;
6064 iterator_wrapper_internal(json_iterator i) : anchor(i)
6068 iterator_wrapper_internal& operator*()
6074 iterator_wrapper_internal& operator++()
6083 bool operator!= (
const iterator_wrapper_internal& o)
6085 return anchor != o.anchor;
6091 switch (anchor.m_object->type())
6096 return std::to_string(array_index);
6102 return anchor.key();
6114 typename json_iterator::reference
value()
const
6116 return anchor.value();
6129 return iterator_wrapper_internal(container.
begin());
6133 iterator_wrapper_internal
end()
6135 return iterator_wrapper_internal(container.
end());
6155 enum class token_type
6174 using lexer_char_t =
unsigned char;
6177 explicit lexer(
const string_t& s) noexcept
6178 : m_stream(
nullptr), m_buffer(s)
6180 m_content =
reinterpret_cast<const lexer_char_t*
>(s.c_str());
6181 m_start = m_cursor = m_content;
6182 m_limit = m_content + s.size();
6184 explicit lexer(std::istream* s) noexcept
6185 : m_stream(s), m_buffer()
6187 getline(*m_stream, m_buffer);
6188 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
6189 m_start = m_cursor = m_content;
6190 m_limit = m_content + m_buffer.size();
6197 lexer(
const lexer&) =
delete;
6211 static string_t to_unicode(
const std::size_t codepoint1,
6212 const std::size_t codepoint2 = 0)
6217 std::size_t codepoint = codepoint1;
6220 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6223 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6237 throw std::invalid_argument(
"missing or wrong low surrogate");
6241 if (codepoint < 0x80)
6244 result.append(1, static_cast<typename string_t::value_type>(codepoint));
6246 else if (codepoint <= 0x7ff)
6249 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
6250 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6252 else if (codepoint <= 0xffff)
6255 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
6256 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6257 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6259 else if (codepoint <= 0x10ffff)
6262 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
6263 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
6264 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6265 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6269 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
6276 static std::string token_type_name(token_type t)
6280 case token_type::uninitialized:
6281 return "<uninitialized>";
6282 case token_type::literal_true:
6283 return "true literal";
6284 case token_type::literal_false:
6285 return "false literal";
6286 case token_type::literal_null:
6287 return "null literal";
6288 case token_type::value_string:
6289 return "string literal";
6290 case token_type::value_number:
6291 return "number literal";
6292 case token_type::begin_array:
6294 case token_type::begin_object:
6296 case token_type::end_array:
6298 case token_type::end_object:
6300 case token_type::name_separator:
6302 case token_type::value_separator:
6304 case token_type::parse_error:
6305 return "<parse error>";
6306 case token_type::end_of_input:
6307 return "<end of input>";
6311 return "unknown token";
6326 token_type scan() noexcept
6337 unsigned int yyaccept = 0;
6338 static const unsigned char yybm[] =
6340 0, 0, 0, 0, 0, 0, 0, 0,
6341 0, 32, 32, 0, 0, 32, 0, 0,
6342 64, 64, 64, 64, 64, 64, 64, 64,
6343 64, 64, 64, 64, 64, 64, 64, 64,
6344 96, 64, 0, 64, 64, 64, 64, 64,
6345 64, 64, 64, 64, 64, 64, 64, 64,
6346 192, 192, 192, 192, 192, 192, 192, 192,
6347 192, 192, 64, 64, 64, 64, 64, 64,
6348 64, 64, 64, 64, 64, 64, 64, 64,
6349 64, 64, 64, 64, 64, 64, 64, 64,
6350 64, 64, 64, 64, 64, 64, 64, 64,
6351 64, 64, 64, 64, 0, 64, 64, 64,
6352 64, 64, 64, 64, 64, 64, 64, 64,
6353 64, 64, 64, 64, 64, 64, 64, 64,
6354 64, 64, 64, 64, 64, 64, 64, 64,
6355 64, 64, 64, 64, 64, 64, 64, 64,
6356 64, 64, 64, 64, 64, 64, 64, 64,
6357 64, 64, 64, 64, 64, 64, 64, 64,
6358 64, 64, 64, 64, 64, 64, 64, 64,
6359 64, 64, 64, 64, 64, 64, 64, 64,
6360 64, 64, 64, 64, 64, 64, 64, 64,
6361 64, 64, 64, 64, 64, 64, 64, 64,
6362 64, 64, 64, 64, 64, 64, 64, 64,
6363 64, 64, 64, 64, 64, 64, 64, 64,
6364 64, 64, 64, 64, 64, 64, 64, 64,
6365 64, 64, 64, 64, 64, 64, 64, 64,
6366 64, 64, 64, 64, 64, 64, 64, 64,
6367 64, 64, 64, 64, 64, 64, 64, 64,
6368 64, 64, 64, 64, 64, 64, 64, 64,
6369 64, 64, 64, 64, 64, 64, 64, 64,
6370 64, 64, 64, 64, 64, 64, 64, 64,
6371 64, 64, 64, 64, 64, 64, 64, 64,
6373 if ((m_limit - m_cursor) < 5)
6386 goto basic_json_parser_28;
6390 goto basic_json_parser_30;
6394 goto basic_json_parser_4;
6401 goto basic_json_parser_2;
6405 goto basic_json_parser_30;
6415 goto basic_json_parser_27;
6419 goto basic_json_parser_30;
6421 goto basic_json_parser_16;
6429 goto basic_json_parser_23;
6431 goto basic_json_parser_30;
6437 goto basic_json_parser_24;
6441 goto basic_json_parser_26;
6443 goto basic_json_parser_18;
6456 goto basic_json_parser_8;
6460 goto basic_json_parser_30;
6462 goto basic_json_parser_10;
6468 goto basic_json_parser_22;
6472 goto basic_json_parser_30;
6474 goto basic_json_parser_20;
6483 goto basic_json_parser_21;
6487 goto basic_json_parser_30;
6489 goto basic_json_parser_12;
6497 goto basic_json_parser_30;
6499 goto basic_json_parser_14;
6505 goto basic_json_parser_6;
6507 goto basic_json_parser_30;
6512 basic_json_parser_2:
6515 goto basic_json_parser_5;
6516 basic_json_parser_3:
6520 basic_json_parser_4:
6522 if (m_limit <= m_cursor)
6527 basic_json_parser_5:
6528 if (yybm[0 + yych] & 32)
6530 goto basic_json_parser_4;
6532 goto basic_json_parser_3;
6533 basic_json_parser_6:
6535 yych = *(m_marker = ++m_cursor);
6538 goto basic_json_parser_64;
6540 basic_json_parser_7:
6542 return token_type::parse_error;
6544 basic_json_parser_8:
6547 return token_type::begin_array;
6549 basic_json_parser_10:
6552 return token_type::end_array;
6554 basic_json_parser_12:
6557 return token_type::begin_object;
6559 basic_json_parser_14:
6562 return token_type::end_object;
6564 basic_json_parser_16:
6567 return token_type::value_separator;
6569 basic_json_parser_18:
6572 return token_type::name_separator;
6574 basic_json_parser_20:
6576 yych = *(m_marker = ++m_cursor);
6579 goto basic_json_parser_60;
6581 goto basic_json_parser_7;
6582 basic_json_parser_21:
6584 yych = *(m_marker = ++m_cursor);
6587 goto basic_json_parser_56;
6589 goto basic_json_parser_7;
6590 basic_json_parser_22:
6592 yych = *(m_marker = ++m_cursor);
6595 goto basic_json_parser_51;
6597 goto basic_json_parser_7;
6598 basic_json_parser_23:
6602 goto basic_json_parser_7;
6606 goto basic_json_parser_50;
6610 goto basic_json_parser_41;
6612 goto basic_json_parser_7;
6613 basic_json_parser_24:
6615 yych = *(m_marker = ++m_cursor);
6620 goto basic_json_parser_43;
6627 goto basic_json_parser_44;
6631 goto basic_json_parser_44;
6634 basic_json_parser_25:
6636 return token_type::value_number;
6638 basic_json_parser_26:
6640 yych = *(m_marker = ++m_cursor);
6641 goto basic_json_parser_42;
6642 basic_json_parser_27:
6644 yych = *(m_marker = ++m_cursor);
6647 goto basic_json_parser_7;
6649 goto basic_json_parser_32;
6650 basic_json_parser_28:
6653 return token_type::end_of_input;
6655 basic_json_parser_30:
6657 goto basic_json_parser_7;
6658 basic_json_parser_31:
6660 if (m_limit <= m_cursor)
6665 basic_json_parser_32:
6666 if (yybm[0 + yych] & 64)
6668 goto basic_json_parser_31;
6672 goto basic_json_parser_33;
6676 goto basic_json_parser_35;
6678 goto basic_json_parser_34;
6679 basic_json_parser_33:
6680 m_cursor = m_marker;
6683 goto basic_json_parser_7;
6687 goto basic_json_parser_25;
6689 basic_json_parser_34:
6691 if (m_limit <= m_cursor)
6702 goto basic_json_parser_31;
6706 goto basic_json_parser_33;
6708 goto basic_json_parser_31;
6716 goto basic_json_parser_33;
6718 goto basic_json_parser_31;
6724 goto basic_json_parser_31;
6726 goto basic_json_parser_33;
6736 goto basic_json_parser_31;
6740 goto basic_json_parser_31;
6742 goto basic_json_parser_33;
6750 goto basic_json_parser_31;
6752 goto basic_json_parser_33;
6758 goto basic_json_parser_31;
6762 goto basic_json_parser_37;
6764 goto basic_json_parser_33;
6768 basic_json_parser_35:
6771 return token_type::value_string;
6773 basic_json_parser_37:
6775 if (m_limit <= m_cursor)
6784 goto basic_json_parser_33;
6788 goto basic_json_parser_33;
6795 goto basic_json_parser_38;
6799 goto basic_json_parser_33;
6803 goto basic_json_parser_33;
6806 basic_json_parser_38:
6808 if (m_limit <= m_cursor)
6817 goto basic_json_parser_33;
6821 goto basic_json_parser_33;
6828 goto basic_json_parser_39;
6832 goto basic_json_parser_33;
6836 goto basic_json_parser_33;
6839 basic_json_parser_39:
6841 if (m_limit <= m_cursor)
6850 goto basic_json_parser_33;
6854 goto basic_json_parser_33;
6861 goto basic_json_parser_40;
6865 goto basic_json_parser_33;
6869 goto basic_json_parser_33;
6872 basic_json_parser_40:
6874 if (m_limit <= m_cursor)
6883 goto basic_json_parser_33;
6887 goto basic_json_parser_31;
6889 goto basic_json_parser_33;
6895 goto basic_json_parser_31;
6899 goto basic_json_parser_33;
6903 goto basic_json_parser_31;
6905 goto basic_json_parser_33;
6907 basic_json_parser_41:
6909 m_marker = ++m_cursor;
6910 if ((m_limit - m_cursor) < 3)
6915 basic_json_parser_42:
6916 if (yybm[0 + yych] & 128)
6918 goto basic_json_parser_41;
6924 goto basic_json_parser_25;
6931 goto basic_json_parser_44;
6935 goto basic_json_parser_44;
6937 goto basic_json_parser_25;
6939 basic_json_parser_43:
6943 goto basic_json_parser_33;
6947 goto basic_json_parser_48;
6949 goto basic_json_parser_33;
6950 basic_json_parser_44:
6956 goto basic_json_parser_33;
6963 goto basic_json_parser_45;
6967 goto basic_json_parser_33;
6971 goto basic_json_parser_46;
6973 goto basic_json_parser_33;
6975 basic_json_parser_45:
6979 goto basic_json_parser_33;
6983 goto basic_json_parser_33;
6985 basic_json_parser_46:
6987 if (m_limit <= m_cursor)
6994 goto basic_json_parser_25;
6998 goto basic_json_parser_46;
7000 goto basic_json_parser_25;
7001 basic_json_parser_48:
7003 m_marker = ++m_cursor;
7004 if ((m_limit - m_cursor) < 3)
7013 goto basic_json_parser_25;
7017 goto basic_json_parser_48;
7019 goto basic_json_parser_25;
7025 goto basic_json_parser_44;
7029 goto basic_json_parser_44;
7031 goto basic_json_parser_25;
7033 basic_json_parser_50:
7035 yych = *(m_marker = ++m_cursor);
7040 goto basic_json_parser_43;
7042 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_51:
7060 goto basic_json_parser_33;
7065 goto basic_json_parser_33;
7070 goto basic_json_parser_33;
7074 return token_type::literal_false;
7076 basic_json_parser_56:
7080 goto basic_json_parser_33;
7085 goto basic_json_parser_33;
7089 return token_type::literal_true;
7091 basic_json_parser_60:
7095 goto basic_json_parser_33;
7100 goto basic_json_parser_33;
7104 return token_type::literal_null;
7106 basic_json_parser_64:
7110 goto basic_json_parser_33;
7122 void yyfill() noexcept
7124 if (not m_stream or not * m_stream)
7129 const ssize_t offset_start = m_start - m_content;
7130 const ssize_t offset_marker = m_marker - m_start;
7131 const ssize_t offset_cursor = m_cursor - m_start;
7133 m_buffer.erase(0, static_cast<size_t>(offset_start));
7135 std::getline(*m_stream, line);
7136 m_buffer +=
"\n" + line;
7138 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
7139 m_start = m_content;
7140 m_marker = m_start + offset_marker;
7141 m_cursor = m_start + offset_cursor;
7142 m_limit = m_start + m_buffer.size() - 1;
7146 string_t get_token() const noexcept
7148 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7149 static_cast<size_t>(m_cursor - m_start));
7176 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7179 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7235 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7236 4).c_str(),
nullptr, 16);
7239 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7242 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
7244 throw std::invalid_argument(
"missing low surrogate");
7248 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7249 (i + 7), 4).c_str(),
nullptr, 16);
7250 result += to_unicode(codepoint, codepoint2);
7257 result += to_unicode(codepoint);
7269 result.append(1, static_cast<typename string_t::value_type>(*i));
7293 long double get_number()
const
7296 typename string_t::value_type* endptr;
7297 const auto float_val = std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start),
7302 return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
7307 std::istream* m_stream;
7311 const lexer_char_t* m_content =
nullptr;
7313 const lexer_char_t* m_start =
nullptr;
7315 const lexer_char_t* m_marker =
nullptr;
7317 const lexer_char_t* m_cursor =
nullptr;
7319 const lexer_char_t* m_limit =
nullptr;
7332 : callback(cb), m_lexer(s)
7340 : callback(cb), m_lexer(&_is)
7349 basic_json result = parse_internal(
true);
7351 expect(lexer::token_type::end_of_input);
7355 return result.is_discarded() ?
basic_json() : result;
7360 basic_json parse_internal(
bool keep)
7366 case lexer::token_type::begin_object:
7379 if (last_token == lexer::token_type::end_object)
7390 unexpect(lexer::token_type::value_separator);
7396 if (last_token == lexer::token_type::value_separator)
7402 expect(lexer::token_type::value_string);
7403 const auto key = m_lexer.get_string();
7405 bool keep_tag =
false;
7421 expect(lexer::token_type::name_separator);
7425 auto value = parse_internal(keep);
7426 if (keep and keep_tag and not
value.is_discarded())
7428 result[key] = std::move(
value);
7431 while (last_token == lexer::token_type::value_separator);
7434 expect(lexer::token_type::end_object);
7444 case lexer::token_type::begin_array:
7457 if (last_token == lexer::token_type::end_array)
7468 unexpect(lexer::token_type::value_separator);
7474 if (last_token == lexer::token_type::value_separator)
7480 auto value = parse_internal(keep);
7481 if (keep and not
value.is_discarded())
7483 result.push_back(std::move(
value));
7486 while (last_token == lexer::token_type::value_separator);
7489 expect(lexer::token_type::end_array);
7499 case lexer::token_type::literal_null:
7506 case lexer::token_type::value_string:
7508 const auto s = m_lexer.get_string();
7514 case lexer::token_type::literal_true:
7518 result.m_value =
true;
7522 case lexer::token_type::literal_false:
7526 result.m_value =
false;
7530 case lexer::token_type::value_number:
7532 auto float_val = m_lexer.get_number();
7536 if (std::isnan(float_val))
7538 throw std::invalid_argument(std::string(
"parse error - ") +
7539 m_lexer.get_token() +
" is not a number");
7546 if (approx(float_val, static_cast<long double>(int_val)))
7550 result.m_value = int_val;
7564 unexpect(last_token);
7576 typename lexer::token_type get_token()
7578 last_token = m_lexer.scan();
7582 void expect(
typename lexer::token_type t)
const
7584 if (t != last_token)
7586 std::string error_msg =
"parse error - unexpected \'";
7587 error_msg += m_lexer.get_token();
7588 error_msg +=
"\' (" + lexer::token_type_name(last_token);
7589 error_msg +=
"); expected " + lexer::token_type_name(t);
7590 throw std::invalid_argument(error_msg);
7594 void unexpect(
typename lexer::token_type t)
const
7596 if (t == last_token)
7598 std::string error_msg =
"parse error - unexpected \'";
7599 error_msg += m_lexer.get_token();
7600 error_msg +=
"\' (";
7601 error_msg += lexer::token_type_name(last_token) +
")";
7602 throw std::invalid_argument(error_msg);
7612 typename lexer::token_type last_token = lexer::token_type::uninitialized;
7650 is_nothrow_move_constructible<nlohmann::json>::value and
7651 is_nothrow_move_assignable<nlohmann::json>::value
7669 const auto& h = hash<nlohmann::json::string_t>();
7687 inline nlohmann::json operator "" _json(
const char* s, std::size_t)
7690 (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_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_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