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());
2896 return m_value.object->find(key)->second;
2900 throw std::domain_error(
"cannot use operator[] with " + type_name());
2932 template<
typename T, std::
size_t n>
2945 return m_value.object->operator[](key);
2949 throw std::domain_error(
"cannot use operator[] with " + type_name());
2981 template<
typename T, std::
size_t n>
2987 return m_value.object->find(key)->second;
2991 throw std::domain_error(
"cannot use operator[] with " + type_name());
3042 template <
class ValueType,
typename
3044 std::is_convertible<basic_json_t, ValueType>::value
3046 ValueType
value(
const typename object_t::key_type& key, ValueType default_value)
const
3052 const auto it =
find(key);
3059 return default_value;
3064 throw std::domain_error(
"cannot use value() with " + type_name());
3072 string_t value(
const typename object_t::key_type& key,
const char* default_value)
const
3190 template <
class InteratorType,
typename
3192 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3193 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3199 if (
this != pos.m_object)
3201 throw std::domain_error(
"iterator does not fit current value");
3204 InteratorType result =
end();
3213 if (not pos.m_it.primitive_iterator.is_begin())
3215 throw std::out_of_range(
"iterator out of range");
3220 delete m_value.string;
3221 m_value.string =
nullptr;
3230 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3236 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3242 throw std::domain_error(
"cannot use erase() with " + type_name());
3291 template <
class InteratorType,
typename
3293 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3294 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3297 InteratorType
erase(InteratorType first, InteratorType last)
3300 if (
this != first.m_object or
this != last.m_object)
3302 throw std::domain_error(
"iterators do not fit current value");
3305 InteratorType result =
end();
3314 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3316 throw std::out_of_range(
"iterators out of range");
3321 delete m_value.string;
3322 m_value.string =
nullptr;
3331 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3332 last.m_it.object_iterator);
3338 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3339 last.m_it.array_iterator);
3345 throw std::domain_error(
"cannot use erase with " + type_name());
3382 return m_value.object->erase(key);
3386 throw std::domain_error(
"cannot use erase() with " + type_name());
3419 throw std::out_of_range(
"index out of range");
3422 m_value.array->erase(m_value.array->begin() +
static_cast<difference_type>(idx));
3426 throw std::domain_error(
"cannot use erase() with " + type_name());
3449 auto result =
end();
3453 result.m_it.object_iterator = m_value.object->find(key);
3465 auto result =
cend();
3469 result.m_it.object_iterator = m_value.object->find(key);
3496 return is_object() ? m_value.object->count(key) : 0;
3785 return m_value.array->empty();
3790 return m_value.object->empty();
3842 return m_value.array->size();
3847 return m_value.object->size();
3896 return m_value.array->max_size();
3901 return m_value.object->max_size();
3953 m_value.number_integer = 0;
3959 m_value.number_float = 0.0;
3965 m_value.boolean =
false;
3971 m_value.string->clear();
3977 m_value.array->clear();
3983 m_value.object->clear();
4018 throw std::domain_error(
"cannot use push_back() with " + type_name());
4029 m_value.array->push_back(std::move(val));
4053 throw std::domain_error(
"cannot use push_back() with " + type_name());
4064 m_value.array->push_back(val);
4102 throw std::domain_error(
"cannot use push_back() with " + type_name());
4113 m_value.object->insert(val);
4152 if (pos.m_object !=
this)
4154 throw std::domain_error(
"iterator does not fit current value");
4159 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4164 throw std::domain_error(
"cannot use insert() with " + type_name());
4205 if (pos.m_object !=
this)
4207 throw std::domain_error(
"iterator does not fit current value");
4212 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4217 throw std::domain_error(
"cannot use insert() with " + type_name());
4252 throw std::domain_error(
"cannot use insert() with " + type_name());
4256 if (pos.m_object !=
this)
4258 throw std::domain_error(
"iterator does not fit current value");
4261 if (first.m_object != last.m_object)
4263 throw std::domain_error(
"iterators do not fit");
4266 if (first.m_object ==
this or last.m_object ==
this)
4268 throw std::domain_error(
"passed iterators may not belong to container");
4273 result.m_it.array_iterator = m_value.array->insert(
4274 pos.m_it.array_iterator,
4275 first.m_it.array_iterator,
4276 last.m_it.array_iterator);
4306 throw std::domain_error(
"cannot use insert() with " + type_name());
4310 if (pos.m_object !=
this)
4312 throw std::domain_error(
"iterator does not fit current value");
4317 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4339 std::is_nothrow_move_constructible<value_t>::value and
4340 std::is_nothrow_move_assignable<value_t>::value and
4341 std::is_nothrow_move_constructible<json_value>::value and
4342 std::is_nothrow_move_assignable<json_value>::value
4345 std::swap(m_type, other.m_type);
4346 std::swap(m_value, other.m_value);
4373 std::swap(*(m_value.array), other);
4377 throw std::domain_error(
"cannot use swap() with " + type_name());
4405 std::swap(*(m_value.object), other);
4409 throw std::domain_error(
"cannot use swap() with " + type_name());
4437 std::swap(*(m_value.string), other);
4441 throw std::domain_error(
"cannot use swap() with " + type_name());
4467 static constexpr std::array<uint8_t, 7> order = {{
4484 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
4513 const auto lhs_type = lhs.type();
4514 const auto rhs_type = rhs.type();
4516 if (lhs_type == rhs_type)
4521 return *lhs.m_value.array == *rhs.m_value.array;
4523 return *lhs.m_value.object == *rhs.m_value.object;
4527 return *lhs.m_value.string == *rhs.m_value.string;
4529 return lhs.m_value.boolean == rhs.m_value.boolean;
4531 return lhs.m_value.number_integer == rhs.m_value.number_integer;
4533 return approx(lhs.m_value.number_float, rhs.m_value.number_float);
4540 return approx(static_cast<number_float_t>(lhs.m_value.number_integer),
4541 rhs.m_value.number_float);
4545 return approx(lhs.m_value.number_float,
4546 static_cast<number_float_t>(rhs.m_value.number_integer));
4601 return not (lhs == rhs);
4633 return not v.is_null();
4662 const auto lhs_type = lhs.type();
4663 const auto rhs_type = rhs.type();
4665 if (lhs_type == rhs_type)
4670 return *lhs.m_value.array < *rhs.m_value.array;
4672 return *lhs.m_value.object < *rhs.m_value.object;
4676 return *lhs.m_value.string < *rhs.m_value.string;
4678 return lhs.m_value.boolean < rhs.m_value.boolean;
4680 return lhs.m_value.number_integer < rhs.m_value.number_integer;
4682 return lhs.m_value.number_float < rhs.m_value.number_float;
4690 rhs.m_value.number_float;
4694 return lhs.m_value.number_float <
4723 return not (rhs < lhs);
4745 return not (lhs <= rhs);
4767 return not (lhs < rhs);
4802 friend std::ostream&
operator<<(std::ostream& o,
const basic_json& j)
4805 const bool pretty_print = (o.width() > 0);
4806 const auto indentation = (pretty_print ? o.width() : 0);
4812 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
4820 friend std::ostream&
operator>>(
const basic_json& j, std::ostream& o)
4861 return parser(s, cb).
parse();
4890 return parser(i, cb).
parse();
4898 return parser(i, cb).
parse();
4926 j = parser(i).
parse();
4936 j = parser(i).
parse();
4978 static std::size_t extra_space(
const string_t& s) noexcept
4980 std::size_t result = 0;
4982 for (
const auto& c : s)
5001 if (c >= 0x00 and c <= 0x1f)
5029 const auto space = extra_space(s);
5036 string_t result(s.size() + space,
'\\');
5037 std::size_t pos = 0;
5039 for (
const auto& c : s)
5046 result[pos + 1] =
'"';
5062 result[pos + 1] =
'b';
5070 result[pos + 1] =
'f';
5078 result[pos + 1] =
'n';
5086 result[pos + 1] =
'r';
5094 result[pos + 1] =
't';
5101 if (c >= 0x00 and c <= 0x1f)
5104 auto hexify = [](
const char v) ->
char
5106 return (v < 10) ? (
'0' + v) : (
'a' + v - 10);
5111 {
'u',
'0',
'0', hexify(c >> 4), hexify(c & 0x0f)
5149 void dump(std::ostream& o,
5150 const bool pretty_print,
5151 const unsigned int indent_step,
5152 const unsigned int current_indent = 0)
const
5155 unsigned int new_indent = current_indent;
5161 if (m_value.object->empty())
5172 new_indent += indent_step;
5176 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5178 if (i != m_value.object->cbegin())
5180 o << (pretty_print ?
",\n" :
",");
5182 o <<
string_t(new_indent,
' ') <<
"\""
5183 << escape_string(i->first) <<
"\":"
5184 << (pretty_print ?
" " :
"");
5185 i->second.dump(o, pretty_print, indent_step, new_indent);
5191 new_indent -= indent_step;
5195 o <<
string_t(new_indent,
' ') +
"}";
5201 if (m_value.array->empty())
5212 new_indent += indent_step;
5216 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5218 if (i != m_value.array->cbegin())
5220 o << (pretty_print ?
",\n" :
",");
5223 i->dump(o, pretty_print, indent_step, new_indent);
5229 new_indent -= indent_step;
5233 o <<
string_t(new_indent,
' ') <<
"]";
5239 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
5245 o << (m_value.boolean ?
"true" :
"false");
5251 o << m_value.number_integer;
5260 o << std::setprecision(std::numeric_limits<number_float_t>::digits10) << m_value.number_float;
5287 json_value m_value = {};
5304 class primitive_iterator_t
5320 bool is_begin()
const
5322 return (m_it == begin_value);
5328 return (m_it == end_value);
5348 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5358 struct internal_iterator
5361 typename object_t::iterator object_iterator;
5363 typename array_t::iterator array_iterator;
5365 primitive_iterator_t primitive_iterator;
5369 : object_iterator(), array_iterator(), primitive_iterator()
5387 class const_iterator :
public std::iterator<std::random_access_iterator_tag, const basic_json>
5390 friend class basic_json;
5410 switch (m_object->m_type)
5414 m_it.object_iterator =
typename object_t::iterator();
5420 m_it.array_iterator =
typename array_t::iterator();
5426 m_it.primitive_iterator = primitive_iterator_t();
5435 switch (m_object->m_type)
5439 m_it.object_iterator = other.m_it.object_iterator;
5445 m_it.array_iterator = other.m_it.array_iterator;
5451 m_it.primitive_iterator = other.m_it.primitive_iterator;
5459 : m_object(other.m_object), m_it(other.m_it)
5464 std::is_nothrow_move_constructible<pointer>::value and
5465 std::is_nothrow_move_assignable<pointer>::value and
5466 std::is_nothrow_move_constructible<internal_iterator>::value and
5467 std::is_nothrow_move_assignable<internal_iterator>::value
5470 std::swap(m_object, other.m_object);
5471 std::swap(m_it, other.m_it);
5479 switch (m_object->m_type)
5483 m_it.object_iterator = m_object->m_value.object->begin();
5489 m_it.array_iterator = m_object->m_value.array->begin();
5496 m_it.primitive_iterator.set_end();
5502 m_it.primitive_iterator.set_begin();
5511 switch (m_object->m_type)
5515 m_it.object_iterator = m_object->m_value.object->end();
5521 m_it.array_iterator = m_object->m_value.array->end();
5527 m_it.primitive_iterator.set_end();
5537 switch (m_object->m_type)
5541 return m_it.object_iterator->second;
5546 return *m_it.array_iterator;
5551 throw std::out_of_range(
"cannot get value");
5556 if (m_it.primitive_iterator.is_begin())
5562 throw std::out_of_range(
"cannot get value");
5571 switch (m_object->m_type)
5575 return &(m_it.object_iterator->second);
5580 return &*m_it.array_iterator;
5585 if (m_it.primitive_iterator.is_begin())
5591 throw std::out_of_range(
"cannot get value");
5600 auto result = *
this;
5608 switch (m_object->m_type)
5612 ++m_it.object_iterator;
5618 ++m_it.array_iterator;
5624 ++m_it.primitive_iterator;
5635 auto result = *
this;
5643 switch (m_object->m_type)
5647 --m_it.object_iterator;
5653 --m_it.array_iterator;
5659 --m_it.primitive_iterator;
5671 if (m_object != other.m_object)
5673 throw std::domain_error(
"cannot compare iterators of different containers");
5676 switch (m_object->m_type)
5680 return (m_it.object_iterator == other.m_it.object_iterator);
5685 return (m_it.array_iterator == other.m_it.array_iterator);
5690 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
5705 if (m_object != other.m_object)
5707 throw std::domain_error(
"cannot compare iterators of different containers");
5710 switch (m_object->m_type)
5714 throw std::domain_error(
"cannot use operator< for object iterators");
5719 return (m_it.array_iterator < other.m_it.array_iterator);
5724 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
5732 return not other.operator < (*this);
5750 switch (m_object->m_type)
5754 throw std::domain_error(
"cannot use operator+= for object iterators");
5759 m_it.array_iterator += i;
5765 m_it.primitive_iterator += i;
5782 auto result = *
this;
5790 auto result = *
this;
5798 switch (m_object->m_type)
5802 throw std::domain_error(
"cannot use operator- for object iterators");
5807 return m_it.array_iterator - other.m_it.array_iterator;
5812 return m_it.primitive_iterator - other.m_it.primitive_iterator;
5820 switch (m_object->m_type)
5824 throw std::domain_error(
"cannot use operator[] for object iterators");
5829 return *(m_it.array_iterator + n);
5834 throw std::out_of_range(
"cannot get value");
5839 if (m_it.primitive_iterator == -n)
5845 throw std::out_of_range(
"cannot get value");
5852 typename object_t::key_type
key()
const
5854 if (m_object->is_object())
5856 return m_it.object_iterator->first;
5860 throw std::domain_error(
"cannot use key() for non-object iterators");
5874 internal_iterator m_it = internal_iterator();
5910 std::is_nothrow_move_constructible<pointer>::value and
5911 std::is_nothrow_move_assignable<pointer>::value and
5912 std::is_nothrow_move_constructible<internal_iterator>::value and
5913 std::is_nothrow_move_assignable<internal_iterator>::value
5979 auto result = *
this;
5987 auto result = *
this;
6027 template<
typename Base>
6028 class json_reverse_iterator :
public std::reverse_iterator<Base>
6046 return base_iterator::operator++(1);
6052 base_iterator::operator++();
6059 return base_iterator::operator--(1);
6065 base_iterator::operator--();
6072 base_iterator::operator+=(i);
6079 auto result = *
this;
6087 auto result = *
this;
6095 return this->base() - other.base();
6105 typename object_t::key_type
key()
const
6107 auto it = --this->base();
6114 auto it = --this->base();
6115 return it.operator * ();
6130 basic_json& container;
6132 using json_iterator = decltype(std::begin(container));
6135 class iterator_wrapper_internal
6139 json_iterator anchor;
6141 size_t array_index = 0;
6145 iterator_wrapper_internal(json_iterator i) : anchor(i)
6149 iterator_wrapper_internal& operator*()
6155 iterator_wrapper_internal& operator++()
6164 bool operator!= (
const iterator_wrapper_internal& o)
6166 return anchor != o.anchor;
6172 switch (anchor.m_object->type())
6177 return std::to_string(array_index);
6183 return anchor.key();
6195 typename json_iterator::reference
value()
const
6197 return anchor.value();
6210 return iterator_wrapper_internal(container.
begin());
6214 iterator_wrapper_internal
end()
6216 return iterator_wrapper_internal(container.
end());
6236 enum class token_type
6255 using lexer_char_t =
unsigned char;
6258 explicit lexer(
const string_t& s) noexcept
6259 : m_stream(
nullptr), m_buffer(s)
6261 m_content =
reinterpret_cast<const lexer_char_t*
>(s.c_str());
6262 m_start = m_cursor = m_content;
6263 m_limit = m_content + s.size();
6265 explicit lexer(std::istream* s) noexcept
6266 : m_stream(s), m_buffer()
6268 getline(*m_stream, m_buffer);
6269 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
6270 m_start = m_cursor = m_content;
6271 m_limit = m_content + m_buffer.size();
6278 lexer(
const lexer&) =
delete;
6292 static string_t to_unicode(
const std::size_t codepoint1,
6293 const std::size_t codepoint2 = 0)
6298 std::size_t codepoint = codepoint1;
6301 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6304 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6318 throw std::invalid_argument(
"missing or wrong low surrogate");
6322 if (codepoint < 0x80)
6325 result.append(1, static_cast<typename string_t::value_type>(codepoint));
6327 else if (codepoint <= 0x7ff)
6330 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
6331 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6333 else if (codepoint <= 0xffff)
6336 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
6337 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6338 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6340 else if (codepoint <= 0x10ffff)
6343 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
6344 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
6345 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6346 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6350 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
6357 static std::string token_type_name(token_type t)
6361 case token_type::uninitialized:
6362 return "<uninitialized>";
6363 case token_type::literal_true:
6364 return "true literal";
6365 case token_type::literal_false:
6366 return "false literal";
6367 case token_type::literal_null:
6368 return "null literal";
6369 case token_type::value_string:
6370 return "string literal";
6371 case token_type::value_number:
6372 return "number literal";
6373 case token_type::begin_array:
6375 case token_type::begin_object:
6377 case token_type::end_array:
6379 case token_type::end_object:
6381 case token_type::name_separator:
6383 case token_type::value_separator:
6385 case token_type::parse_error:
6386 return "<parse error>";
6387 case token_type::end_of_input:
6388 return "<end of input>";
6392 return "unknown token";
6407 token_type scan() noexcept
6418 unsigned int yyaccept = 0;
6419 static const unsigned char yybm[] =
6421 0, 0, 0, 0, 0, 0, 0, 0,
6422 0, 32, 32, 0, 0, 32, 0, 0,
6423 64, 64, 64, 64, 64, 64, 64, 64,
6424 64, 64, 64, 64, 64, 64, 64, 64,
6425 96, 64, 0, 64, 64, 64, 64, 64,
6426 64, 64, 64, 64, 64, 64, 64, 64,
6427 192, 192, 192, 192, 192, 192, 192, 192,
6428 192, 192, 64, 64, 64, 64, 64, 64,
6429 64, 64, 64, 64, 64, 64, 64, 64,
6430 64, 64, 64, 64, 64, 64, 64, 64,
6431 64, 64, 64, 64, 64, 64, 64, 64,
6432 64, 64, 64, 64, 0, 64, 64, 64,
6433 64, 64, 64, 64, 64, 64, 64, 64,
6434 64, 64, 64, 64, 64, 64, 64, 64,
6435 64, 64, 64, 64, 64, 64, 64, 64,
6436 64, 64, 64, 64, 64, 64, 64, 64,
6437 64, 64, 64, 64, 64, 64, 64, 64,
6438 64, 64, 64, 64, 64, 64, 64, 64,
6439 64, 64, 64, 64, 64, 64, 64, 64,
6440 64, 64, 64, 64, 64, 64, 64, 64,
6441 64, 64, 64, 64, 64, 64, 64, 64,
6442 64, 64, 64, 64, 64, 64, 64, 64,
6443 64, 64, 64, 64, 64, 64, 64, 64,
6444 64, 64, 64, 64, 64, 64, 64, 64,
6445 64, 64, 64, 64, 64, 64, 64, 64,
6446 64, 64, 64, 64, 64, 64, 64, 64,
6447 64, 64, 64, 64, 64, 64, 64, 64,
6448 64, 64, 64, 64, 64, 64, 64, 64,
6449 64, 64, 64, 64, 64, 64, 64, 64,
6450 64, 64, 64, 64, 64, 64, 64, 64,
6451 64, 64, 64, 64, 64, 64, 64, 64,
6452 64, 64, 64, 64, 64, 64, 64, 64,
6454 if ((m_limit - m_cursor) < 5)
6467 goto basic_json_parser_28;
6471 goto basic_json_parser_30;
6475 goto basic_json_parser_4;
6482 goto basic_json_parser_2;
6486 goto basic_json_parser_30;
6496 goto basic_json_parser_27;
6500 goto basic_json_parser_30;
6502 goto basic_json_parser_16;
6510 goto basic_json_parser_23;
6512 goto basic_json_parser_30;
6518 goto basic_json_parser_24;
6522 goto basic_json_parser_26;
6524 goto basic_json_parser_18;
6537 goto basic_json_parser_8;
6541 goto basic_json_parser_30;
6543 goto basic_json_parser_10;
6549 goto basic_json_parser_22;
6553 goto basic_json_parser_30;
6555 goto basic_json_parser_20;
6564 goto basic_json_parser_21;
6568 goto basic_json_parser_30;
6570 goto basic_json_parser_12;
6578 goto basic_json_parser_30;
6580 goto basic_json_parser_14;
6586 goto basic_json_parser_6;
6588 goto basic_json_parser_30;
6593 basic_json_parser_2:
6596 goto basic_json_parser_5;
6597 basic_json_parser_3:
6601 basic_json_parser_4:
6603 if (m_limit <= m_cursor)
6608 basic_json_parser_5:
6609 if (yybm[0 + yych] & 32)
6611 goto basic_json_parser_4;
6613 goto basic_json_parser_3;
6614 basic_json_parser_6:
6616 yych = *(m_marker = ++m_cursor);
6619 goto basic_json_parser_64;
6621 basic_json_parser_7:
6623 return token_type::parse_error;
6625 basic_json_parser_8:
6628 return token_type::begin_array;
6630 basic_json_parser_10:
6633 return token_type::end_array;
6635 basic_json_parser_12:
6638 return token_type::begin_object;
6640 basic_json_parser_14:
6643 return token_type::end_object;
6645 basic_json_parser_16:
6648 return token_type::value_separator;
6650 basic_json_parser_18:
6653 return token_type::name_separator;
6655 basic_json_parser_20:
6657 yych = *(m_marker = ++m_cursor);
6660 goto basic_json_parser_60;
6662 goto basic_json_parser_7;
6663 basic_json_parser_21:
6665 yych = *(m_marker = ++m_cursor);
6668 goto basic_json_parser_56;
6670 goto basic_json_parser_7;
6671 basic_json_parser_22:
6673 yych = *(m_marker = ++m_cursor);
6676 goto basic_json_parser_51;
6678 goto basic_json_parser_7;
6679 basic_json_parser_23:
6683 goto basic_json_parser_7;
6687 goto basic_json_parser_50;
6691 goto basic_json_parser_41;
6693 goto basic_json_parser_7;
6694 basic_json_parser_24:
6696 yych = *(m_marker = ++m_cursor);
6701 goto basic_json_parser_43;
6708 goto basic_json_parser_44;
6712 goto basic_json_parser_44;
6715 basic_json_parser_25:
6717 return token_type::value_number;
6719 basic_json_parser_26:
6721 yych = *(m_marker = ++m_cursor);
6722 goto basic_json_parser_42;
6723 basic_json_parser_27:
6725 yych = *(m_marker = ++m_cursor);
6728 goto basic_json_parser_7;
6730 goto basic_json_parser_32;
6731 basic_json_parser_28:
6734 return token_type::end_of_input;
6736 basic_json_parser_30:
6738 goto basic_json_parser_7;
6739 basic_json_parser_31:
6741 if (m_limit <= m_cursor)
6746 basic_json_parser_32:
6747 if (yybm[0 + yych] & 64)
6749 goto basic_json_parser_31;
6753 goto basic_json_parser_33;
6757 goto basic_json_parser_35;
6759 goto basic_json_parser_34;
6760 basic_json_parser_33:
6761 m_cursor = m_marker;
6764 goto basic_json_parser_7;
6768 goto basic_json_parser_25;
6770 basic_json_parser_34:
6772 if (m_limit <= m_cursor)
6783 goto basic_json_parser_31;
6787 goto basic_json_parser_33;
6789 goto basic_json_parser_31;
6797 goto basic_json_parser_33;
6799 goto basic_json_parser_31;
6805 goto basic_json_parser_31;
6807 goto basic_json_parser_33;
6817 goto basic_json_parser_31;
6821 goto basic_json_parser_31;
6823 goto basic_json_parser_33;
6831 goto basic_json_parser_31;
6833 goto basic_json_parser_33;
6839 goto basic_json_parser_31;
6843 goto basic_json_parser_37;
6845 goto basic_json_parser_33;
6849 basic_json_parser_35:
6852 return token_type::value_string;
6854 basic_json_parser_37:
6856 if (m_limit <= m_cursor)
6865 goto basic_json_parser_33;
6869 goto basic_json_parser_33;
6876 goto basic_json_parser_38;
6880 goto basic_json_parser_33;
6884 goto basic_json_parser_33;
6887 basic_json_parser_38:
6889 if (m_limit <= m_cursor)
6898 goto basic_json_parser_33;
6902 goto basic_json_parser_33;
6909 goto basic_json_parser_39;
6913 goto basic_json_parser_33;
6917 goto basic_json_parser_33;
6920 basic_json_parser_39:
6922 if (m_limit <= m_cursor)
6931 goto basic_json_parser_33;
6935 goto basic_json_parser_33;
6942 goto basic_json_parser_40;
6946 goto basic_json_parser_33;
6950 goto basic_json_parser_33;
6953 basic_json_parser_40:
6955 if (m_limit <= m_cursor)
6964 goto basic_json_parser_33;
6968 goto basic_json_parser_31;
6970 goto basic_json_parser_33;
6976 goto basic_json_parser_31;
6980 goto basic_json_parser_33;
6984 goto basic_json_parser_31;
6986 goto basic_json_parser_33;
6988 basic_json_parser_41:
6990 m_marker = ++m_cursor;
6991 if ((m_limit - m_cursor) < 3)
6996 basic_json_parser_42:
6997 if (yybm[0 + yych] & 128)
6999 goto basic_json_parser_41;
7005 goto basic_json_parser_25;
7012 goto basic_json_parser_44;
7016 goto basic_json_parser_44;
7018 goto basic_json_parser_25;
7020 basic_json_parser_43:
7024 goto basic_json_parser_33;
7028 goto basic_json_parser_48;
7030 goto basic_json_parser_33;
7031 basic_json_parser_44:
7037 goto basic_json_parser_33;
7044 goto basic_json_parser_45;
7048 goto basic_json_parser_33;
7052 goto basic_json_parser_46;
7054 goto basic_json_parser_33;
7056 basic_json_parser_45:
7060 goto basic_json_parser_33;
7064 goto basic_json_parser_33;
7066 basic_json_parser_46:
7068 if (m_limit <= m_cursor)
7075 goto basic_json_parser_25;
7079 goto basic_json_parser_46;
7081 goto basic_json_parser_25;
7082 basic_json_parser_48:
7084 m_marker = ++m_cursor;
7085 if ((m_limit - m_cursor) < 3)
7094 goto basic_json_parser_25;
7098 goto basic_json_parser_48;
7100 goto basic_json_parser_25;
7106 goto basic_json_parser_44;
7110 goto basic_json_parser_44;
7112 goto basic_json_parser_25;
7114 basic_json_parser_50:
7116 yych = *(m_marker = ++m_cursor);
7121 goto basic_json_parser_43;
7123 goto basic_json_parser_25;
7129 goto basic_json_parser_44;
7133 goto basic_json_parser_44;
7135 goto basic_json_parser_25;
7137 basic_json_parser_51:
7141 goto basic_json_parser_33;
7146 goto basic_json_parser_33;
7151 goto basic_json_parser_33;
7155 return token_type::literal_false;
7157 basic_json_parser_56:
7161 goto basic_json_parser_33;
7166 goto basic_json_parser_33;
7170 return token_type::literal_true;
7172 basic_json_parser_60:
7176 goto basic_json_parser_33;
7181 goto basic_json_parser_33;
7185 return token_type::literal_null;
7187 basic_json_parser_64:
7191 goto basic_json_parser_33;
7203 void yyfill() noexcept
7205 if (not m_stream or not * m_stream)
7210 const ssize_t offset_start = m_start - m_content;
7211 const ssize_t offset_marker = m_marker - m_start;
7212 const ssize_t offset_cursor = m_cursor - m_start;
7214 m_buffer.erase(0, static_cast<size_t>(offset_start));
7216 std::getline(*m_stream, line);
7217 m_buffer +=
"\n" + line;
7219 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
7220 m_start = m_content;
7221 m_marker = m_start + offset_marker;
7222 m_cursor = m_start + offset_cursor;
7223 m_limit = m_start + m_buffer.size() - 1;
7227 string_t get_token() const noexcept
7229 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7230 static_cast<size_t>(m_cursor - m_start));
7257 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7260 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7316 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7317 4).c_str(),
nullptr, 16);
7320 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7323 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
7325 throw std::invalid_argument(
"missing low surrogate");
7329 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7330 (i + 7), 4).c_str(),
nullptr, 16);
7331 result += to_unicode(codepoint, codepoint2);
7338 result += to_unicode(codepoint);
7350 result.append(1, static_cast<typename string_t::value_type>(*i));
7374 long double get_number()
const
7377 typename string_t::value_type* endptr;
7378 const auto float_val = std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start),
7383 return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
7388 std::istream* m_stream;
7392 const lexer_char_t* m_content =
nullptr;
7394 const lexer_char_t* m_start =
nullptr;
7396 const lexer_char_t* m_marker =
nullptr;
7398 const lexer_char_t* m_cursor =
nullptr;
7400 const lexer_char_t* m_limit =
nullptr;
7413 : callback(cb), m_lexer(s)
7421 : callback(cb), m_lexer(&_is)
7430 basic_json result = parse_internal(
true);
7432 expect(lexer::token_type::end_of_input);
7436 return result.is_discarded() ?
basic_json() : result;
7441 basic_json parse_internal(
bool keep)
7447 case lexer::token_type::begin_object:
7460 if (last_token == lexer::token_type::end_object)
7471 unexpect(lexer::token_type::value_separator);
7477 if (last_token == lexer::token_type::value_separator)
7483 expect(lexer::token_type::value_string);
7484 const auto key = m_lexer.get_string();
7486 bool keep_tag =
false;
7502 expect(lexer::token_type::name_separator);
7506 auto value = parse_internal(keep);
7507 if (keep and keep_tag and not
value.is_discarded())
7509 result[key] = std::move(
value);
7512 while (last_token == lexer::token_type::value_separator);
7515 expect(lexer::token_type::end_object);
7525 case lexer::token_type::begin_array:
7538 if (last_token == lexer::token_type::end_array)
7549 unexpect(lexer::token_type::value_separator);
7555 if (last_token == lexer::token_type::value_separator)
7561 auto value = parse_internal(keep);
7562 if (keep and not
value.is_discarded())
7564 result.push_back(std::move(
value));
7567 while (last_token == lexer::token_type::value_separator);
7570 expect(lexer::token_type::end_array);
7580 case lexer::token_type::literal_null:
7587 case lexer::token_type::value_string:
7589 const auto s = m_lexer.get_string();
7595 case lexer::token_type::literal_true:
7599 result.m_value =
true;
7603 case lexer::token_type::literal_false:
7607 result.m_value =
false;
7611 case lexer::token_type::value_number:
7613 auto float_val = m_lexer.get_number();
7617 if (std::isnan(float_val))
7619 throw std::invalid_argument(std::string(
"parse error - ") +
7620 m_lexer.get_token() +
" is not a number");
7627 if (approx(float_val, static_cast<long double>(int_val)))
7631 result.m_value = int_val;
7645 unexpect(last_token);
7657 typename lexer::token_type get_token()
7659 last_token = m_lexer.scan();
7663 void expect(
typename lexer::token_type t)
const
7665 if (t != last_token)
7667 std::string error_msg =
"parse error - unexpected \'";
7668 error_msg += m_lexer.get_token();
7669 error_msg +=
"\' (" + lexer::token_type_name(last_token);
7670 error_msg +=
"); expected " + lexer::token_type_name(t);
7671 throw std::invalid_argument(error_msg);
7675 void unexpect(
typename lexer::token_type t)
const
7677 if (t == last_token)
7679 std::string error_msg =
"parse error - unexpected \'";
7680 error_msg += m_lexer.get_token();
7681 error_msg +=
"\' (";
7682 error_msg += lexer::token_type_name(last_token) +
")";
7683 throw std::invalid_argument(error_msg);
7693 typename lexer::token_type last_token = lexer::token_type::uninitialized;
7731 is_nothrow_move_constructible<nlohmann::json>::value and
7732 is_nothrow_move_assignable<nlohmann::json>::value
7750 const auto& h = hash<nlohmann::json::string_t>();
7768 inline nlohmann::json operator "" _json(
const char* s, std::size_t)
7771 (const_cast<char*>(s)));
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
iterator_wrapper(basic_json &cont)
construct iterator wrapper from a container
bool operator!=(const const_iterator &other) const
comparison: not equal
iterator insert(const_iterator pos, basic_json &&val)
inserts element
iterator operator++(int)
post-increment (it++)
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
static basic_json object(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an object from an initializer list
const_reference operator[](size_type idx) const
access specified array element
reference operator[](const T(&key)[n])
access specified object element
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
const_iterator & operator--()
pre-decrement (–it)
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
const_iterator & operator=(const_iterator other) noexcept( std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value )
copy assignment
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
reference & operator=(basic_json other) noexcept( std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value )
copy assignment
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
json_reverse_iterator operator--(int)
post-decrement (it–)
StringType string_t
a type for a string
void push_back(const typename object_t::value_type &val)
add an object to an object
basic_json(boolean_t val)
create a boolean (explicit)
static basic_json array(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an array from an initializer list
iterator & operator++()
pre-increment (++it)
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
const_iterator & operator++()
pre-increment (++it)
difference_type operator-(const json_reverse_iterator &other) const
return difference
basic_json<> json
default JSON class
reference front()
access the first element
bool is_array() const noexcept
return whether value is an array
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
json_reverse_iterator(const typename base_iterator::iterator_type &it)
create reverse iterator from iterator
a class to store JSON values
json_reverse_iterator & operator--()
pre-decrement (–it)
basic_json(const object_t &val)
create an object (explicit)
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
void push_back(basic_json &&val)
add an object to an array
const_iterator cbegin() const
returns a const iterator to the first element
bool is_string() const noexcept
return whether value is a string
iterator & operator+=(difference_type i)
add to iterator
const PointerType get_ptr() const noexcept
get a pointer value (implicit)
basic_json(const CompatibleStringType &val)
create a string (implicit)
the parser read ] and finished processing a JSON array
const_iterator base_iterator
reference operator+=(basic_json &&val)
add an object to an array
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
a mutable random access iterator for the basic_json class
iterator & operator-=(difference_type i)
subtract from iterator
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
reference operator[](const typename object_t::key_type &key)
access specified object element
difference_type operator-(const iterator &other) const
reference value() const
return the value of an iterator
const_iterator end() const
returns a const iterator to one past the last element
const_iterator(const const_iterator &other) noexcept
copy constructor
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
object_t::key_type key() const
return the key of an object iterator
iterator end()
returns an iterator to one past the last element
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
reference operator*()
return a reference to the value pointed to by the iterator
reverse_iterator rend()
returns an iterator to the reverse-end
bool is_object() const noexcept
return whether value is an object
const_iterator operator-(difference_type i)
subtract from iterator
bool is_discarded() const noexcept
return whether value is discarded
basic_json(const CompatibleArrayType &val)
create an array (implicit)
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
const_reverse_iterator rend() const
returns a const reverse iterator to one before the first
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
bool is_boolean() const noexcept
return whether value is a boolean
iterator begin()
returns an iterator to the first element
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
reference operator+=(const basic_json &val)
add an object to an array
AllocatorType< basic_json > allocator_type
the allocator type
basic_json(const number_float_t val)
create a floating-point number (explicit)
bool is_number_integer() const noexcept
return whether value is an integer number
iterator operator+(difference_type i)
add to iterator
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
basic_json(const typename string_t::value_type *val)
create a string (explicit)
const_iterator()=default
default constructor
the parser read [ and started to process a JSON array
iterator find(typename object_t::key_type key)
find an element in a JSON object
basic_json(const value_t value_type)
create an empty value with a given type
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
iterator & operator--()
pre-decrement (–it)
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
pointer operator->() const
dereference the iterator
discarded by the the parser callback function
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
const_iterator cend() const
returns a const iterator to one past the last element
typename Base::reference reference
the reference type for the pointed-to element
size_type size() const noexcept
returns the number of elements
static allocator_type get_allocator()
returns the allocator associated with the container
object (unordered set of name/value pairs)
reference at(size_type idx)
access specified array element with bounds checking
the parser read } and finished processing a JSON object
iterator()=default
default constructor
json_reverse_iterator(const base_iterator &it)
create reverse iterator from base class
iterator_wrapper_internal end()
return iterator end (needed for range-based for)
value_t type() const noexcept
return the type of the JSON value (explicit)
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
object_t::key_type key() const
return the key of an object iterator
bool is_structured() const noexcept
return whether type is structured
namespace for Niels Lohmann
typename basic_json::difference_type difference_type
a type to represent differences between iterators
void swap(array_t &other)
exchanges the values
reverse_iterator rbegin()
returns an iterator to the reverse-beginning
reference operator+=(const typename object_t::value_type &val)
add an object to an object
iterator_wrapper_internal begin()
return iterator begin (needed for range-based for)
reference operator[](difference_type n) const
access to successor
std::size_t size_type
a type to represent container sizes
const_reverse_iterator rbegin() const
returns a const reverse iterator to the last element
basic_json(const basic_json &other)
copy constructor
const_iterator operator+(difference_type i)
add to iterator
value_t
the JSON type enumeration
const value_type & const_reference
the type of an element const reference
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
bool is_null() const noexcept
return whether value is null
void swap(string_t &other)
exchanges the values
reference value() const
return the value of an iterator
const_iterator operator--(int)
post-decrement (it–)
void erase(const size_type idx)
remove element from a JSON array given an index
void clear() noexcept
clears the contents
pointer operator->()
dereference the iterator
basic_json value_type
the type of elements in a basic_json container
array (ordered collection of values)
const_reference front() const
access the first element
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
std::ptrdiff_t difference_type
a type to represent differences between iterators
const_iterator & operator+=(difference_type i)
add to iterator
basic_json(std::initializer_list< basic_json > init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
difference_type operator-(const const_iterator &other) const
return difference
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
bool is_number() const noexcept
return whether value is a number
BooleanType boolean_t
a type for a boolean
const_reverse_iterator crend() const
returns a const reverse iterator to one before the first
basic_json() noexcept=default
create a null object (implicitly)
the parser read a key of a value in an object
bool empty() const noexcept
checks whether the container is empty
string_t value(const typename object_t::key_type &key, const char *default_value) const
overload for a default value of type const char*
void swap(reference other) noexcept( std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value )
exchanges the values
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
const_reverse_iterator crbegin() const
returns a const reverse iterator to the last element
reference value() const
return the value of an iterator
const_iterator(pointer object)
constructor for a given JSON instance
friend bool operator<(const value_t lhs, const value_t rhs)
comparison operator for JSON types
iterator(pointer object) noexcept
constructor for a given JSON instance
bool operator<(const const_iterator &other) const
comparison: smaller
string_t dump(const int indent=-1) const
serialization
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
const_iterator & operator-=(difference_type i)
subtract from iterator
basic_json(const int val)
create an integer number from an enum type (explicit)
basic_json(const array_t &val)
create an array (explicit)
number value (floating-point)
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
json_reverse_iterator operator++(int)
post-increment (it++)
PointerType get_ptr() noexcept
get a pointer value (implicit)
const_iterator(const iterator &other)
copy constructor given a nonconst iterator
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
InteratorType erase(InteratorType pos)
remove element given an iterator
bool operator<=(const const_iterator &other) const
comparison: less than or equal
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
reference back()
access the last element
bool is_number_float() const noexcept
return whether value is a floating-point number
the parser read { and started to process a JSON object
const_iterator operator++(int)
post-increment (it++)
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
basic_json(const string_t &val)
create a string (explicit)
iterator(const iterator &other) noexcept
copy constructor
const_reference back() const
access the last element
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
size_type count(typename object_t::key_type key) const
returns the number of occurrences of a key in a JSON object
size_type max_size() const noexcept
returns the maximum possible number of elements
void push_back(const basic_json &val)
add an object to an array
bool operator==(const const_iterator &other) const
comparison: equal
json_reverse_iterator & operator++()
pre-increment (++it)
bool operator>(const const_iterator &other) const
comparison: greater than
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
basic_json(basic_json &&other) noexcept
move constructor
const_reference operator[](const T(&key)[n]) const
read-only access specified object element
const_iterator begin() const
returns a const iterator to the first element
const_reference at(size_type idx) const
access specified array element with bounds checking
json_reverse_iterator & operator+=(difference_type i)
add to iterator
a const random access iterator for the basic_json class
a template for a reverse iterator class
void swap(object_t &other)
exchanges the values
std::bidirectional_iterator_tag iterator_category
the category of the iterator
bool is_primitive() const noexcept
return whether type is primitive
iterator insert(const_iterator pos, const basic_json &val)
inserts element
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
reference operator[](difference_type n) const
access to successor
NumberIntegerType number_integer_t
a type for a number (integer)
reference operator[](difference_type n) const
access to successor
reference operator*() const
return a reference to the value pointed to by the iterator
value_type & reference
the type of an element reference
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
the parser finished reading a JSON value
NumberFloatType number_float_t
a type for a number (floating-point)
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
iterator & operator=(iterator other) noexcept( std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value )
copy assignment
basic_json(const CompatibleObjectType &val)
create an object (implicit)
reference operator[](size_type idx)
access specified array element
iterator operator--(int)
post-decrement (it–)
json_reverse_iterator operator+(difference_type i) const
add to iterator
parse_event_t
JSON callback events.
iterator operator-(difference_type i)
subtract from iterator
wrapper to access iterator member functions in range-based for