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));
2571 template<
typename ValueType,
typename
2573 not std::is_pointer<ValueType>::value
2575 operator ValueType()
const
2578 return get<ValueType>();
2617 return m_value.array->at(idx);
2621 throw std::domain_error(
"cannot use at() with " + type_name());
2651 return m_value.array->at(idx);
2655 throw std::domain_error(
"cannot use at() with " + type_name());
2689 return m_value.object->at(key);
2693 throw std::domain_error(
"cannot use at() with " + type_name());
2727 return m_value.object->at(key);
2731 throw std::domain_error(
"cannot use at() with " + type_name());
2765 m_value.array = create<array_t>();
2771 for (
size_t i = m_value.array->size(); i <= idx; ++i)
2776 return m_value.array->operator[](idx);
2780 throw std::domain_error(
"cannot use operator[] with " + type_name());
2807 return m_value.array->operator[](idx);
2811 throw std::domain_error(
"cannot use operator[] with " + type_name());
2847 m_value.object = create<object_t>();
2853 return m_value.object->operator[](key);
2857 throw std::domain_error(
"cannot use operator[] with " + type_name());
2889 template<
typename T, std::
size_t n>
2902 return m_value.object->operator[](key);
2906 throw std::domain_error(
"cannot use operator[] with " + type_name());
2957 template <
class ValueType,
typename
2959 std::is_convertible<basic_json_t, ValueType>::value
2961 ValueType
value(
const typename object_t::key_type& key, ValueType default_value)
const
2967 const auto it =
find(key);
2974 return default_value;
2979 throw std::domain_error(
"cannot use value() with " + type_name());
2987 string_t value(
const typename object_t::key_type& key,
const char* default_value)
const
3105 template <
class InteratorType,
typename
3107 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3108 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3114 if (
this != pos.m_object)
3116 throw std::domain_error(
"iterator does not fit current value");
3119 InteratorType result =
end();
3128 if (not pos.m_it.primitive_iterator.is_begin())
3130 throw std::out_of_range(
"iterator out of range");
3135 delete m_value.string;
3136 m_value.string =
nullptr;
3145 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3151 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3157 throw std::domain_error(
"cannot use erase() with " + type_name());
3206 template <
class InteratorType,
typename
3208 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3209 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3212 InteratorType
erase(InteratorType first, InteratorType last)
3215 if (
this != first.m_object or
this != last.m_object)
3217 throw std::domain_error(
"iterators do not fit current value");
3220 InteratorType result =
end();
3229 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3231 throw std::out_of_range(
"iterators out of range");
3236 delete m_value.string;
3237 m_value.string =
nullptr;
3246 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3247 last.m_it.object_iterator);
3253 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3254 last.m_it.array_iterator);
3260 throw std::domain_error(
"cannot use erase with " + type_name());
3297 return m_value.object->erase(key);
3301 throw std::domain_error(
"cannot use erase() with " + type_name());
3334 throw std::out_of_range(
"index out of range");
3337 m_value.array->erase(m_value.array->begin() +
static_cast<difference_type>(idx));
3341 throw std::domain_error(
"cannot use erase() with " + type_name());
3364 auto result =
end();
3368 result.m_it.object_iterator = m_value.object->find(key);
3380 auto result =
cend();
3384 result.m_it.object_iterator = m_value.object->find(key);
3411 return is_object() ? m_value.object->count(key) : 0;
3700 return m_value.array->empty();
3705 return m_value.object->empty();
3757 return m_value.array->size();
3762 return m_value.object->size();
3811 return m_value.array->max_size();
3816 return m_value.object->max_size();
3868 m_value.number_integer = 0;
3874 m_value.number_float = 0.0;
3880 m_value.boolean =
false;
3886 m_value.string->clear();
3892 m_value.array->clear();
3898 m_value.object->clear();
3933 throw std::domain_error(
"cannot use push_back() with " + type_name());
3944 m_value.array->push_back(std::move(val));
3968 throw std::domain_error(
"cannot use push_back() with " + type_name());
3979 m_value.array->push_back(val);
4017 throw std::domain_error(
"cannot use push_back() with " + type_name());
4028 m_value.object->insert(val);
4067 if (pos.m_object !=
this)
4069 throw std::domain_error(
"iterator does not fit current value");
4074 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4079 throw std::domain_error(
"cannot use insert() with " + type_name());
4120 if (pos.m_object !=
this)
4122 throw std::domain_error(
"iterator does not fit current value");
4127 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4132 throw std::domain_error(
"cannot use insert() with " + type_name());
4167 throw std::domain_error(
"cannot use insert() with " + type_name());
4171 if (pos.m_object !=
this)
4173 throw std::domain_error(
"iterator does not fit current value");
4176 if (first.m_object != last.m_object)
4178 throw std::domain_error(
"iterators do not fit");
4181 if (first.m_object ==
this or last.m_object ==
this)
4183 throw std::domain_error(
"passed iterators may not belong to container");
4188 result.m_it.array_iterator = m_value.array->insert(
4189 pos.m_it.array_iterator,
4190 first.m_it.array_iterator,
4191 last.m_it.array_iterator);
4221 throw std::domain_error(
"cannot use insert() with " + type_name());
4225 if (pos.m_object !=
this)
4227 throw std::domain_error(
"iterator does not fit current value");
4232 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4254 std::is_nothrow_move_constructible<value_t>::value and
4255 std::is_nothrow_move_assignable<value_t>::value and
4256 std::is_nothrow_move_constructible<json_value>::value and
4257 std::is_nothrow_move_assignable<json_value>::value
4260 std::swap(m_type, other.m_type);
4261 std::swap(m_value, other.m_value);
4288 std::swap(*(m_value.array), other);
4292 throw std::domain_error(
"cannot use swap() with " + type_name());
4320 std::swap(*(m_value.object), other);
4324 throw std::domain_error(
"cannot use swap() with " + type_name());
4352 std::swap(*(m_value.string), other);
4356 throw std::domain_error(
"cannot use swap() with " + type_name());
4382 static constexpr std::array<uint8_t, 7> order = {{
4399 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
4428 const auto lhs_type = lhs.type();
4429 const auto rhs_type = rhs.type();
4431 if (lhs_type == rhs_type)
4436 return *lhs.m_value.array == *rhs.m_value.array;
4438 return *lhs.m_value.object == *rhs.m_value.object;
4442 return *lhs.m_value.string == *rhs.m_value.string;
4444 return lhs.m_value.boolean == rhs.m_value.boolean;
4446 return lhs.m_value.number_integer == rhs.m_value.number_integer;
4448 return approx(lhs.m_value.number_float, rhs.m_value.number_float);
4455 return approx(static_cast<number_float_t>(lhs.m_value.number_integer),
4456 rhs.m_value.number_float);
4460 return approx(lhs.m_value.number_float,
4461 static_cast<number_float_t>(rhs.m_value.number_integer));
4516 return not (lhs == rhs);
4548 return not v.is_null();
4577 const auto lhs_type = lhs.type();
4578 const auto rhs_type = rhs.type();
4580 if (lhs_type == rhs_type)
4585 return *lhs.m_value.array < *rhs.m_value.array;
4587 return *lhs.m_value.object < *rhs.m_value.object;
4591 return *lhs.m_value.string < *rhs.m_value.string;
4593 return lhs.m_value.boolean < rhs.m_value.boolean;
4595 return lhs.m_value.number_integer < rhs.m_value.number_integer;
4597 return lhs.m_value.number_float < rhs.m_value.number_float;
4605 rhs.m_value.number_float;
4609 return lhs.m_value.number_float <
4638 return not (rhs < lhs);
4660 return not (lhs <= rhs);
4682 return not (lhs < rhs);
4717 friend std::ostream&
operator<<(std::ostream& o,
const basic_json& j)
4720 const bool pretty_print = (o.width() > 0);
4721 const auto indentation = (pretty_print ? o.width() : 0);
4727 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
4735 friend std::ostream&
operator>>(
const basic_json& j, std::ostream& o)
4776 return parser(s, cb).
parse();
4805 return parser(i, cb).
parse();
4813 return parser(i, cb).
parse();
4841 j = parser(i).
parse();
4851 j = parser(i).
parse();
4893 static std::size_t extra_space(
const string_t& s) noexcept
4895 std::size_t result = 0;
4897 for (
const auto& c : s)
4916 if (c >= 0x00 and c <= 0x1f)
4944 const auto space = extra_space(s);
4951 string_t result(s.size() + space,
'\\');
4952 std::size_t pos = 0;
4954 for (
const auto& c : s)
4961 result[pos + 1] =
'"';
4977 result[pos + 1] =
'b';
4985 result[pos + 1] =
'f';
4993 result[pos + 1] =
'n';
5001 result[pos + 1] =
'r';
5009 result[pos + 1] =
't';
5016 if (c >= 0x00 and c <= 0x1f)
5019 auto hexify = [](
const char v) ->
char
5021 return (v < 10) ? (
'0' + v) : (
'a' + v - 10);
5026 {
'u',
'0',
'0', hexify(c >> 4), hexify(c & 0x0f)
5064 void dump(std::ostream& o,
5065 const bool pretty_print,
5066 const unsigned int indent_step,
5067 const unsigned int current_indent = 0)
const
5070 unsigned int new_indent = current_indent;
5076 if (m_value.object->empty())
5087 new_indent += indent_step;
5091 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5093 if (i != m_value.object->cbegin())
5095 o << (pretty_print ?
",\n" :
",");
5097 o <<
string_t(new_indent,
' ') <<
"\""
5098 << escape_string(i->first) <<
"\":"
5099 << (pretty_print ?
" " :
"");
5100 i->second.dump(o, pretty_print, indent_step, new_indent);
5106 new_indent -= indent_step;
5110 o <<
string_t(new_indent,
' ') +
"}";
5116 if (m_value.array->empty())
5127 new_indent += indent_step;
5131 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5133 if (i != m_value.array->cbegin())
5135 o << (pretty_print ?
",\n" :
",");
5138 i->dump(o, pretty_print, indent_step, new_indent);
5144 new_indent -= indent_step;
5148 o <<
string_t(new_indent,
' ') <<
"]";
5154 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
5160 o << (m_value.boolean ?
"true" :
"false");
5166 o << m_value.number_integer;
5175 o << std::setprecision(std::numeric_limits<number_float_t>::digits10) << m_value.number_float;
5202 json_value m_value = {};
5219 class primitive_iterator_t
5235 bool is_begin()
const
5237 return (m_it == begin_value);
5243 return (m_it == end_value);
5263 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5273 struct internal_iterator
5276 typename object_t::iterator object_iterator;
5278 typename array_t::iterator array_iterator;
5280 primitive_iterator_t primitive_iterator;
5284 : object_iterator(), array_iterator(), primitive_iterator()
5302 class const_iterator :
public std::iterator<std::random_access_iterator_tag, const basic_json>
5305 friend class basic_json;
5325 switch (m_object->m_type)
5329 m_it.object_iterator =
typename object_t::iterator();
5335 m_it.array_iterator =
typename array_t::iterator();
5341 m_it.primitive_iterator = primitive_iterator_t();
5350 switch (m_object->m_type)
5354 m_it.object_iterator = other.m_it.object_iterator;
5360 m_it.array_iterator = other.m_it.array_iterator;
5366 m_it.primitive_iterator = other.m_it.primitive_iterator;
5374 : m_object(other.m_object), m_it(other.m_it)
5379 std::is_nothrow_move_constructible<pointer>::value and
5380 std::is_nothrow_move_assignable<pointer>::value and
5381 std::is_nothrow_move_constructible<internal_iterator>::value and
5382 std::is_nothrow_move_assignable<internal_iterator>::value
5385 std::swap(m_object, other.m_object);
5386 std::swap(m_it, other.m_it);
5394 switch (m_object->m_type)
5398 m_it.object_iterator = m_object->m_value.object->begin();
5404 m_it.array_iterator = m_object->m_value.array->begin();
5411 m_it.primitive_iterator.set_end();
5417 m_it.primitive_iterator.set_begin();
5426 switch (m_object->m_type)
5430 m_it.object_iterator = m_object->m_value.object->end();
5436 m_it.array_iterator = m_object->m_value.array->end();
5442 m_it.primitive_iterator.set_end();
5452 switch (m_object->m_type)
5456 return m_it.object_iterator->second;
5461 return *m_it.array_iterator;
5466 throw std::out_of_range(
"cannot get value");
5471 if (m_it.primitive_iterator.is_begin())
5477 throw std::out_of_range(
"cannot get value");
5486 switch (m_object->m_type)
5490 return &(m_it.object_iterator->second);
5495 return &*m_it.array_iterator;
5500 if (m_it.primitive_iterator.is_begin())
5506 throw std::out_of_range(
"cannot get value");
5515 auto result = *
this;
5523 switch (m_object->m_type)
5527 ++m_it.object_iterator;
5533 ++m_it.array_iterator;
5539 ++m_it.primitive_iterator;
5550 auto result = *
this;
5558 switch (m_object->m_type)
5562 --m_it.object_iterator;
5568 --m_it.array_iterator;
5574 --m_it.primitive_iterator;
5586 if (m_object != other.m_object)
5588 throw std::domain_error(
"cannot compare iterators of different containers");
5591 switch (m_object->m_type)
5595 return (m_it.object_iterator == other.m_it.object_iterator);
5600 return (m_it.array_iterator == other.m_it.array_iterator);
5605 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
5620 if (m_object != other.m_object)
5622 throw std::domain_error(
"cannot compare iterators of different containers");
5625 switch (m_object->m_type)
5629 throw std::domain_error(
"cannot use operator< for object iterators");
5634 return (m_it.array_iterator < other.m_it.array_iterator);
5639 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
5647 return not other.operator < (*this);
5665 switch (m_object->m_type)
5669 throw std::domain_error(
"cannot use operator+= for object iterators");
5674 m_it.array_iterator += i;
5680 m_it.primitive_iterator += i;
5697 auto result = *
this;
5705 auto result = *
this;
5713 switch (m_object->m_type)
5717 throw std::domain_error(
"cannot use operator- for object iterators");
5722 return m_it.array_iterator - other.m_it.array_iterator;
5727 return m_it.primitive_iterator - other.m_it.primitive_iterator;
5735 switch (m_object->m_type)
5739 throw std::domain_error(
"cannot use operator[] for object iterators");
5744 return *(m_it.array_iterator + n);
5749 throw std::out_of_range(
"cannot get value");
5754 if (m_it.primitive_iterator == -n)
5760 throw std::out_of_range(
"cannot get value");
5767 typename object_t::key_type
key()
const
5769 if (m_object->is_object())
5771 return m_it.object_iterator->first;
5775 throw std::domain_error(
"cannot use key() for non-object iterators");
5789 internal_iterator m_it = internal_iterator();
5825 std::is_nothrow_move_constructible<pointer>::value and
5826 std::is_nothrow_move_assignable<pointer>::value and
5827 std::is_nothrow_move_constructible<internal_iterator>::value and
5828 std::is_nothrow_move_assignable<internal_iterator>::value
5894 auto result = *
this;
5902 auto result = *
this;
5942 template<
typename Base>
5943 class json_reverse_iterator :
public std::reverse_iterator<Base>
5961 return base_iterator::operator++(1);
5967 base_iterator::operator++();
5974 return base_iterator::operator--(1);
5980 base_iterator::operator--();
5987 base_iterator::operator+=(i);
5994 auto result = *
this;
6002 auto result = *
this;
6010 return this->base() - other.base();
6020 typename object_t::key_type
key()
const
6022 auto it = --this->base();
6029 auto it = --this->base();
6030 return it.operator * ();
6045 basic_json& container;
6047 using json_iterator = decltype(std::begin(container));
6050 class iterator_wrapper_internal
6054 json_iterator anchor;
6056 size_t array_index = 0;
6060 iterator_wrapper_internal(json_iterator i) : anchor(i)
6064 iterator_wrapper_internal& operator*()
6070 iterator_wrapper_internal& operator++()
6079 bool operator!= (
const iterator_wrapper_internal& o)
6081 return anchor != o.anchor;
6087 switch (anchor.m_object->type())
6092 return std::to_string(array_index);
6098 return anchor.key();
6110 typename json_iterator::reference
value()
const
6112 return anchor.value();
6125 return iterator_wrapper_internal(container.
begin());
6129 iterator_wrapper_internal
end()
6131 return iterator_wrapper_internal(container.
end());
6151 enum class token_type
6170 using lexer_char_t =
unsigned char;
6173 explicit lexer(
const string_t& s) noexcept
6174 : m_stream(
nullptr), m_buffer(s)
6176 m_content =
reinterpret_cast<const lexer_char_t*
>(s.c_str());
6177 m_start = m_cursor = m_content;
6178 m_limit = m_content + s.size();
6180 explicit lexer(std::istream* s) noexcept
6181 : m_stream(s), m_buffer()
6183 getline(*m_stream, m_buffer);
6184 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
6185 m_start = m_cursor = m_content;
6186 m_limit = m_content + m_buffer.size();
6193 lexer(
const lexer&) =
delete;
6207 static string_t to_unicode(
const std::size_t codepoint1,
6208 const std::size_t codepoint2 = 0)
6213 std::size_t codepoint = codepoint1;
6216 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6219 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6233 throw std::invalid_argument(
"missing or wrong low surrogate");
6237 if (codepoint < 0x80)
6240 result.append(1, static_cast<typename string_t::value_type>(codepoint));
6242 else if (codepoint <= 0x7ff)
6245 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
6246 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6248 else if (codepoint <= 0xffff)
6251 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
6252 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6253 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6255 else if (codepoint <= 0x10ffff)
6258 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
6259 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
6260 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6261 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6265 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
6272 static std::string token_type_name(token_type t)
6276 case token_type::uninitialized:
6277 return "<uninitialized>";
6278 case token_type::literal_true:
6279 return "true literal";
6280 case token_type::literal_false:
6281 return "false literal";
6282 case token_type::literal_null:
6283 return "null literal";
6284 case token_type::value_string:
6285 return "string literal";
6286 case token_type::value_number:
6287 return "number literal";
6288 case token_type::begin_array:
6290 case token_type::begin_object:
6292 case token_type::end_array:
6294 case token_type::end_object:
6296 case token_type::name_separator:
6298 case token_type::value_separator:
6300 case token_type::parse_error:
6301 return "<parse error>";
6302 case token_type::end_of_input:
6303 return "<end of input>";
6317 token_type scan() noexcept
6328 unsigned int yyaccept = 0;
6329 static const unsigned char yybm[] =
6331 0, 0, 0, 0, 0, 0, 0, 0,
6332 0, 32, 32, 0, 0, 32, 0, 0,
6333 64, 64, 64, 64, 64, 64, 64, 64,
6334 64, 64, 64, 64, 64, 64, 64, 64,
6335 96, 64, 0, 64, 64, 64, 64, 64,
6336 64, 64, 64, 64, 64, 64, 64, 64,
6337 192, 192, 192, 192, 192, 192, 192, 192,
6338 192, 192, 64, 64, 64, 64, 64, 64,
6339 64, 64, 64, 64, 64, 64, 64, 64,
6340 64, 64, 64, 64, 64, 64, 64, 64,
6341 64, 64, 64, 64, 64, 64, 64, 64,
6342 64, 64, 64, 64, 0, 64, 64, 64,
6343 64, 64, 64, 64, 64, 64, 64, 64,
6344 64, 64, 64, 64, 64, 64, 64, 64,
6345 64, 64, 64, 64, 64, 64, 64, 64,
6346 64, 64, 64, 64, 64, 64, 64, 64,
6347 64, 64, 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, 64, 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,
6364 if ((m_limit - m_cursor) < 5)
6377 goto basic_json_parser_28;
6381 goto basic_json_parser_30;
6385 goto basic_json_parser_4;
6392 goto basic_json_parser_2;
6396 goto basic_json_parser_30;
6406 goto basic_json_parser_27;
6410 goto basic_json_parser_30;
6412 goto basic_json_parser_16;
6420 goto basic_json_parser_23;
6422 goto basic_json_parser_30;
6428 goto basic_json_parser_24;
6432 goto basic_json_parser_26;
6434 goto basic_json_parser_18;
6447 goto basic_json_parser_8;
6451 goto basic_json_parser_30;
6453 goto basic_json_parser_10;
6459 goto basic_json_parser_22;
6463 goto basic_json_parser_30;
6465 goto basic_json_parser_20;
6474 goto basic_json_parser_21;
6478 goto basic_json_parser_30;
6480 goto basic_json_parser_12;
6488 goto basic_json_parser_30;
6490 goto basic_json_parser_14;
6496 goto basic_json_parser_6;
6498 goto basic_json_parser_30;
6503 basic_json_parser_2:
6506 goto basic_json_parser_5;
6507 basic_json_parser_3:
6511 basic_json_parser_4:
6513 if (m_limit <= m_cursor)
6518 basic_json_parser_5:
6519 if (yybm[0 + yych] & 32)
6521 goto basic_json_parser_4;
6523 goto basic_json_parser_3;
6524 basic_json_parser_6:
6526 yych = *(m_marker = ++m_cursor);
6529 goto basic_json_parser_64;
6531 basic_json_parser_7:
6533 return token_type::parse_error;
6535 basic_json_parser_8:
6538 return token_type::begin_array;
6540 basic_json_parser_10:
6543 return token_type::end_array;
6545 basic_json_parser_12:
6548 return token_type::begin_object;
6550 basic_json_parser_14:
6553 return token_type::end_object;
6555 basic_json_parser_16:
6558 return token_type::value_separator;
6560 basic_json_parser_18:
6563 return token_type::name_separator;
6565 basic_json_parser_20:
6567 yych = *(m_marker = ++m_cursor);
6570 goto basic_json_parser_60;
6572 goto basic_json_parser_7;
6573 basic_json_parser_21:
6575 yych = *(m_marker = ++m_cursor);
6578 goto basic_json_parser_56;
6580 goto basic_json_parser_7;
6581 basic_json_parser_22:
6583 yych = *(m_marker = ++m_cursor);
6586 goto basic_json_parser_51;
6588 goto basic_json_parser_7;
6589 basic_json_parser_23:
6593 goto basic_json_parser_7;
6597 goto basic_json_parser_50;
6601 goto basic_json_parser_41;
6603 goto basic_json_parser_7;
6604 basic_json_parser_24:
6606 yych = *(m_marker = ++m_cursor);
6611 goto basic_json_parser_43;
6618 goto basic_json_parser_44;
6622 goto basic_json_parser_44;
6625 basic_json_parser_25:
6627 return token_type::value_number;
6629 basic_json_parser_26:
6631 yych = *(m_marker = ++m_cursor);
6632 goto basic_json_parser_42;
6633 basic_json_parser_27:
6635 yych = *(m_marker = ++m_cursor);
6638 goto basic_json_parser_7;
6640 goto basic_json_parser_32;
6641 basic_json_parser_28:
6644 return token_type::end_of_input;
6646 basic_json_parser_30:
6648 goto basic_json_parser_7;
6649 basic_json_parser_31:
6651 if (m_limit <= m_cursor)
6656 basic_json_parser_32:
6657 if (yybm[0 + yych] & 64)
6659 goto basic_json_parser_31;
6663 goto basic_json_parser_33;
6667 goto basic_json_parser_35;
6669 goto basic_json_parser_34;
6670 basic_json_parser_33:
6671 m_cursor = m_marker;
6674 goto basic_json_parser_7;
6678 goto basic_json_parser_25;
6680 basic_json_parser_34:
6682 if (m_limit <= m_cursor)
6693 goto basic_json_parser_31;
6697 goto basic_json_parser_33;
6699 goto basic_json_parser_31;
6707 goto basic_json_parser_33;
6709 goto basic_json_parser_31;
6715 goto basic_json_parser_31;
6717 goto basic_json_parser_33;
6727 goto basic_json_parser_31;
6731 goto basic_json_parser_31;
6733 goto basic_json_parser_33;
6741 goto basic_json_parser_31;
6743 goto basic_json_parser_33;
6749 goto basic_json_parser_31;
6753 goto basic_json_parser_37;
6755 goto basic_json_parser_33;
6759 basic_json_parser_35:
6762 return token_type::value_string;
6764 basic_json_parser_37:
6766 if (m_limit <= m_cursor)
6775 goto basic_json_parser_33;
6779 goto basic_json_parser_33;
6786 goto basic_json_parser_38;
6790 goto basic_json_parser_33;
6794 goto basic_json_parser_33;
6797 basic_json_parser_38:
6799 if (m_limit <= m_cursor)
6808 goto basic_json_parser_33;
6812 goto basic_json_parser_33;
6819 goto basic_json_parser_39;
6823 goto basic_json_parser_33;
6827 goto basic_json_parser_33;
6830 basic_json_parser_39:
6832 if (m_limit <= m_cursor)
6841 goto basic_json_parser_33;
6845 goto basic_json_parser_33;
6852 goto basic_json_parser_40;
6856 goto basic_json_parser_33;
6860 goto basic_json_parser_33;
6863 basic_json_parser_40:
6865 if (m_limit <= m_cursor)
6874 goto basic_json_parser_33;
6878 goto basic_json_parser_31;
6880 goto basic_json_parser_33;
6886 goto basic_json_parser_31;
6890 goto basic_json_parser_33;
6894 goto basic_json_parser_31;
6896 goto basic_json_parser_33;
6898 basic_json_parser_41:
6900 m_marker = ++m_cursor;
6901 if ((m_limit - m_cursor) < 3)
6906 basic_json_parser_42:
6907 if (yybm[0 + yych] & 128)
6909 goto basic_json_parser_41;
6915 goto basic_json_parser_25;
6922 goto basic_json_parser_44;
6926 goto basic_json_parser_44;
6928 goto basic_json_parser_25;
6930 basic_json_parser_43:
6934 goto basic_json_parser_33;
6938 goto basic_json_parser_48;
6940 goto basic_json_parser_33;
6941 basic_json_parser_44:
6947 goto basic_json_parser_33;
6954 goto basic_json_parser_45;
6958 goto basic_json_parser_33;
6962 goto basic_json_parser_46;
6964 goto basic_json_parser_33;
6966 basic_json_parser_45:
6970 goto basic_json_parser_33;
6974 goto basic_json_parser_33;
6976 basic_json_parser_46:
6978 if (m_limit <= m_cursor)
6985 goto basic_json_parser_25;
6989 goto basic_json_parser_46;
6991 goto basic_json_parser_25;
6992 basic_json_parser_48:
6994 m_marker = ++m_cursor;
6995 if ((m_limit - m_cursor) < 3)
7004 goto basic_json_parser_25;
7008 goto basic_json_parser_48;
7010 goto basic_json_parser_25;
7016 goto basic_json_parser_44;
7020 goto basic_json_parser_44;
7022 goto basic_json_parser_25;
7024 basic_json_parser_50:
7026 yych = *(m_marker = ++m_cursor);
7031 goto basic_json_parser_43;
7033 goto basic_json_parser_25;
7039 goto basic_json_parser_44;
7043 goto basic_json_parser_44;
7045 goto basic_json_parser_25;
7047 basic_json_parser_51:
7051 goto basic_json_parser_33;
7056 goto basic_json_parser_33;
7061 goto basic_json_parser_33;
7065 return token_type::literal_false;
7067 basic_json_parser_56:
7071 goto basic_json_parser_33;
7076 goto basic_json_parser_33;
7080 return token_type::literal_true;
7082 basic_json_parser_60:
7086 goto basic_json_parser_33;
7091 goto basic_json_parser_33;
7095 return token_type::literal_null;
7097 basic_json_parser_64:
7101 goto basic_json_parser_33;
7113 void yyfill() noexcept
7115 if (not m_stream or not * m_stream)
7120 const ssize_t offset_start = m_start - m_content;
7121 const ssize_t offset_marker = m_marker - m_start;
7122 const ssize_t offset_cursor = m_cursor - m_start;
7124 m_buffer.erase(0, static_cast<size_t>(offset_start));
7126 std::getline(*m_stream, line);
7127 m_buffer +=
"\n" + line;
7129 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
7130 m_start = m_content;
7131 m_marker = m_start + offset_marker;
7132 m_cursor = m_start + offset_cursor;
7133 m_limit = m_start + m_buffer.size() - 1;
7137 string_t get_token() const noexcept
7139 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7140 static_cast<size_t>(m_cursor - m_start));
7167 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7170 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7226 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7227 4).c_str(),
nullptr, 16);
7230 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7233 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
7235 throw std::invalid_argument(
"missing low surrogate");
7239 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7240 (i + 7), 4).c_str(),
nullptr, 16);
7241 result += to_unicode(codepoint, codepoint2);
7248 result += to_unicode(codepoint);
7260 result.append(1, static_cast<typename string_t::value_type>(*i));
7284 long double get_number()
const
7287 typename string_t::value_type* endptr;
7288 const auto float_val = std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start),
7293 return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
7298 std::istream* m_stream;
7302 const lexer_char_t* m_content =
nullptr;
7304 const lexer_char_t* m_start =
nullptr;
7306 const lexer_char_t* m_marker =
nullptr;
7308 const lexer_char_t* m_cursor =
nullptr;
7310 const lexer_char_t* m_limit =
nullptr;
7323 : callback(cb), m_lexer(s)
7331 : callback(cb), m_lexer(&_is)
7340 basic_json result = parse_internal(
true);
7342 expect(lexer::token_type::end_of_input);
7346 return result.is_discarded() ?
basic_json() : result;
7351 basic_json parse_internal(
bool keep)
7357 case lexer::token_type::begin_object:
7370 if (last_token == lexer::token_type::end_object)
7381 unexpect(lexer::token_type::value_separator);
7387 if (last_token == lexer::token_type::value_separator)
7393 expect(lexer::token_type::value_string);
7394 const auto key = m_lexer.get_string();
7396 bool keep_tag =
false;
7412 expect(lexer::token_type::name_separator);
7416 auto value = parse_internal(keep);
7417 if (keep and keep_tag and not
value.is_discarded())
7419 result[key] = std::move(
value);
7422 while (last_token == lexer::token_type::value_separator);
7425 expect(lexer::token_type::end_object);
7435 case lexer::token_type::begin_array:
7448 if (last_token == lexer::token_type::end_array)
7459 unexpect(lexer::token_type::value_separator);
7465 if (last_token == lexer::token_type::value_separator)
7471 auto value = parse_internal(keep);
7472 if (keep and not
value.is_discarded())
7474 result.push_back(std::move(
value));
7477 while (last_token == lexer::token_type::value_separator);
7480 expect(lexer::token_type::end_array);
7490 case lexer::token_type::literal_null:
7497 case lexer::token_type::value_string:
7499 const auto s = m_lexer.get_string();
7505 case lexer::token_type::literal_true:
7509 result.m_value =
true;
7513 case lexer::token_type::literal_false:
7517 result.m_value =
false;
7521 case lexer::token_type::value_number:
7523 auto float_val = m_lexer.get_number();
7527 if (std::isnan(float_val))
7529 throw std::invalid_argument(std::string(
"parse error - ") +
7530 m_lexer.get_token() +
" is not a number");
7537 if (approx(float_val, static_cast<long double>(int_val)))
7541 result.m_value = int_val;
7555 unexpect(last_token);
7567 typename lexer::token_type get_token()
7569 last_token = m_lexer.scan();
7573 void expect(
typename lexer::token_type t)
const
7575 if (t != last_token)
7577 std::string error_msg =
"parse error - unexpected \'";
7578 error_msg += m_lexer.get_token();
7579 error_msg +=
"\' (" + lexer::token_type_name(last_token);
7580 error_msg +=
"); expected " + lexer::token_type_name(t);
7581 throw std::invalid_argument(error_msg);
7585 void unexpect(
typename lexer::token_type t)
const
7587 if (t == last_token)
7589 std::string error_msg =
"parse error - unexpected \'";
7590 error_msg += m_lexer.get_token();
7591 error_msg +=
"\' (";
7592 error_msg += lexer::token_type_name(last_token) +
")";
7593 throw std::invalid_argument(error_msg);
7603 typename lexer::token_type last_token = lexer::token_type::uninitialized;
7641 is_nothrow_move_constructible<nlohmann::json>::value and
7642 is_nothrow_move_assignable<nlohmann::json>::value
7660 const auto& h = hash<nlohmann::json::string_t>();
7678 inline nlohmann::json operator "" _json(
const char* s, std::size_t)
7681 (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