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), m_value(value)
910 basic_json(
std::nullptr_t) noexcept
934 : m_type(
value_t::object), m_value(value)
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(value),
end(value));
993 : m_type(
value_t::array), m_value(value)
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(value),
end(value));
1059 : m_type(
value_t::string), m_value(value)
1109 template <
class CompatibleStringType,
typename
1111 std::is_constructible<string_t, CompatibleStringType>::value,
int>::type
1132 : m_type(
value_t::boolean), m_value(value)
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(value)
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>(
value))
1259 : m_type(
value_t::number_float), m_value(value)
1262 if (not std::isfinite(value))
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,
1385 for (
const auto& element : init)
1387 if (not element.is_array() or element.size() != 2
1388 or not element[0].is_string())
1398 if (not type_deduction)
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>(
count,
value);
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
2165 ? T(m_value.object->begin(), m_value.object->end())
2166 :
throw std::domain_error(
"type must be object, but is " + type_name());
2174 :
throw std::domain_error(
"type must be object, but is " + type_name());
2178 template <
class T,
typename
2180 std::is_convertible<basic_json_t, typename T::value_type>::value and
2181 not std::is_same<basic_json_t, typename T::value_type>::value and
2182 not std::is_arithmetic<T>::value and
2183 not std::is_convertible<std::string, T>::value and
2184 not has_mapped_type<T>::value
2186 T get_impl(T*)
const
2191 std::transform(m_value.array->begin(), m_value.array->end(),
2192 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2194 return i.get<
typename T::value_type>();
2200 throw std::domain_error(
"type must be array, but is " + type_name());
2205 template <
class T,
typename
2207 std::is_convertible<basic_json_t, T>::value and
2208 not std::is_same<basic_json_t, T>::value
2210 std::vector<T> get_impl(std::vector<T>*)
const
2214 std::vector<T> to_vector;
2215 to_vector.reserve(m_value.array->size());
2216 std::transform(m_value.array->begin(), m_value.array->end(),
2217 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2225 throw std::domain_error(
"type must be array, but is " + type_name());
2230 template <
class T,
typename
2232 std::is_same<basic_json, typename T::value_type>::value and
2233 not has_mapped_type<T>::value
2235 T get_impl(T*)
const
2238 ? T(m_value.array->begin(), m_value.array->end())
2239 :
throw std::domain_error(
"type must be array, but is " + type_name());
2247 :
throw std::domain_error(
"type must be array, but is " + type_name());
2251 template <
typename T,
typename
2253 std::is_convertible<string_t, T>::value
2255 T get_impl(T*)
const
2259 :
throw std::domain_error(
"type must be string, but is " + type_name());
2263 template<
typename T,
typename
2265 std::is_arithmetic<T>::value
2267 T get_impl(T*)
const
2273 return static_cast<T
>(m_value.number_integer);
2278 return static_cast<T
>(m_value.number_float);
2283 throw std::domain_error(
"type must be number, but is " + type_name());
2293 :
throw std::domain_error(
"type must be boolean, but is " + type_name());
2299 return is_object() ? m_value.object :
nullptr;
2305 return is_object() ? m_value.object :
nullptr;
2311 return is_array() ? m_value.array :
nullptr;
2317 return is_array() ? m_value.array :
nullptr;
2323 return is_string() ? m_value.string :
nullptr;
2329 return is_string() ? m_value.string :
nullptr;
2335 return is_boolean() ? &m_value.boolean :
nullptr;
2341 return is_boolean() ? &m_value.boolean :
nullptr;
2406 template<
typename ValueType,
typename
2408 not std::is_pointer<ValueType>::value
2410 ValueType
get()
const
2412 return get_impl(static_cast<ValueType*>(
nullptr));
2441 template<
typename PointerType,
typename
2443 std::is_pointer<PointerType>::value
2445 PointerType
get() noexcept
2448 return get_ptr<PointerType>();
2455 template<
typename PointerType,
typename
2457 std::is_pointer<PointerType>::value
2459 const PointerType
get()
const noexcept
2462 return get_ptr<PointerType>();
2490 template<
typename PointerType,
typename
2492 std::is_pointer<PointerType>::value
2497 return get_impl_ptr(static_cast<PointerType>(
nullptr));
2504 template<
typename PointerType,
typename
2506 std::is_pointer<PointerType>::value
2507 and std::is_const<typename std::remove_pointer<PointerType>::type>
::value
2512 return get_impl_ptr(static_cast<const PointerType>(
nullptr));
2541 template<
typename ValueType,
typename
2543 not std::is_pointer<ValueType>::value
2545 operator ValueType()
const
2548 return get<ValueType>();
2586 ? m_value.array->at(idx)
2587 :
throw std::domain_error(
"cannot use at() with " + type_name());
2615 ? m_value.array->at(idx)
2616 :
throw std::domain_error(
"cannot use at() with " + type_name());
2648 ? m_value.object->at(key)
2649 :
throw std::domain_error(
"cannot use at() with " + type_name());
2681 ? m_value.object->at(key)
2682 :
throw std::domain_error(
"cannot use at() with " + type_name());
2715 m_value.array = create<array_t>();
2721 for (
size_t i = m_value.array->size(); i <= idx; ++i)
2726 return m_value.array->operator[](idx);
2730 throw std::domain_error(
"cannot use operator[] with " + type_name());
2756 ? m_value.array->operator[](idx)
2757 :
throw std::domain_error(
"cannot use operator[] with " + type_name());
2792 m_value.object = create<object_t>();
2797 ? m_value.object->operator[](key)
2798 :
throw std::domain_error(
"cannot use operator[] with " + type_name());
2829 template<
typename T, std::
size_t n>
2841 ? m_value.object->operator[](key)
2842 :
throw std::domain_error(
"cannot use operator[] with " + type_name());
2892 template <
class ValueType,
typename
2894 std::is_convertible<basic_json_t, ValueType>::value
2896 ValueType
value(
const typename object_t::key_type& key, ValueType default_value)
const
2902 const auto it =
find(key);
2909 return default_value;
2914 throw std::domain_error(
"cannot use value() with " + type_name());
2922 string_t value(
const typename object_t::key_type& key,
const char* default_value)
const
3040 template <
class InteratorType,
typename
3042 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3043 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3049 if (
this != pos.m_object)
3051 throw std::domain_error(
"iterator does not fit current value");
3054 InteratorType result =
end();
3063 if (not pos.m_it.primitive_iterator.is_begin())
3065 throw std::out_of_range(
"iterator out of range");
3070 delete m_value.string;
3071 m_value.string =
nullptr;
3080 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3086 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3092 throw std::domain_error(
"cannot use erase() with " + type_name());
3141 template <
class InteratorType,
typename
3143 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3144 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3147 InteratorType
erase(InteratorType first, InteratorType last)
3150 if (
this != first.m_object or
this != last.m_object)
3152 throw std::domain_error(
"iterators do not fit current value");
3155 InteratorType result =
end();
3164 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3166 throw std::out_of_range(
"iterators out of range");
3171 delete m_value.string;
3172 m_value.string =
nullptr;
3181 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3182 last.m_it.object_iterator);
3188 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3189 last.m_it.array_iterator);
3195 throw std::domain_error(
"cannot use erase with " + type_name());
3231 ? m_value.object->erase(key)
3232 :
throw std::domain_error(
"cannot use erase() with " + type_name());
3264 throw std::out_of_range(
"index out of range");
3267 m_value.array->erase(m_value.array->begin() +
static_cast<difference_type>(idx));
3271 throw std::domain_error(
"cannot use erase() with " + type_name());
3294 auto result =
end();
3298 result.m_it.object_iterator = m_value.object->find(key);
3310 auto result =
cend();
3314 result.m_it.object_iterator = m_value.object->find(key);
3341 return is_object() ? m_value.object->count(key) : 0;
3630 return m_value.array->empty();
3635 return m_value.object->empty();
3687 return m_value.array->size();
3692 return m_value.object->size();
3741 return m_value.array->max_size();
3746 return m_value.object->max_size();
3798 m_value.number_integer = 0;
3804 m_value.number_float = 0.0;
3810 m_value.boolean =
false;
3816 m_value.string->clear();
3822 m_value.array->clear();
3828 m_value.object->clear();
3863 throw std::domain_error(
"cannot use push_back() with " + type_name());
3874 m_value.array->push_back(std::move(
value));
3898 throw std::domain_error(
"cannot use push_back() with " + type_name());
3909 m_value.array->push_back(value);
3947 throw std::domain_error(
"cannot use push_back() with " + type_name());
3958 m_value.object->insert(value);
3997 if (pos.m_object !=
this)
3999 throw std::domain_error(
"iterator does not fit current value");
4004 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, value);
4009 throw std::domain_error(
"cannot use insert() with " + type_name());
4050 if (pos.m_object !=
this)
4052 throw std::domain_error(
"iterator does not fit current value");
4057 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, count, value);
4062 throw std::domain_error(
"cannot use insert() with " + type_name());
4097 throw std::domain_error(
"cannot use insert() with " + type_name());
4101 if (pos.m_object !=
this)
4103 throw std::domain_error(
"iterator does not fit current value");
4106 if (first.m_object != last.m_object)
4108 throw std::domain_error(
"iterators do not fit");
4111 if (first.m_object ==
this or last.m_object ==
this)
4113 throw std::domain_error(
"passed iterators may not belong to container");
4118 result.m_it.array_iterator = m_value.array->insert(
4119 pos.m_it.array_iterator,
4120 first.m_it.array_iterator,
4121 last.m_it.array_iterator);
4151 throw std::domain_error(
"cannot use insert() with " + type_name());
4155 if (pos.m_object !=
this)
4157 throw std::domain_error(
"iterator does not fit current value");
4162 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4184 std::is_nothrow_move_constructible<value_t>::value and
4185 std::is_nothrow_move_assignable<value_t>::value and
4186 std::is_nothrow_move_constructible<json_value>::value and
4187 std::is_nothrow_move_assignable<json_value>::value
4190 std::swap(m_type, other.m_type);
4191 std::swap(m_value, other.m_value);
4218 std::swap(*(m_value.array), other);
4222 throw std::domain_error(
"cannot use swap() with " + type_name());
4250 std::swap(*(m_value.object), other);
4254 throw std::domain_error(
"cannot use swap() with " + type_name());
4282 std::swap(*(m_value.string), other);
4286 throw std::domain_error(
"cannot use swap() with " + type_name());
4312 static constexpr std::array<uint8_t, 7> order = {{
4329 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
4358 const auto lhs_type = lhs.type();
4359 const auto rhs_type = rhs.type();
4361 if (lhs_type == rhs_type)
4366 return *lhs.m_value.array == *rhs.m_value.array;
4368 return *lhs.m_value.object == *rhs.m_value.object;
4372 return *lhs.m_value.string == *rhs.m_value.string;
4374 return lhs.m_value.boolean == rhs.m_value.boolean;
4376 return lhs.m_value.number_integer == rhs.m_value.number_integer;
4378 return approx(lhs.m_value.number_float, rhs.m_value.number_float);
4385 return approx(static_cast<number_float_t>(lhs.m_value.number_integer),
4386 rhs.m_value.number_float);
4390 return approx(lhs.m_value.number_float,
4391 static_cast<number_float_t>(rhs.m_value.number_integer));
4446 return not (lhs == rhs);
4478 return not v.is_null();
4507 const auto lhs_type = lhs.type();
4508 const auto rhs_type = rhs.type();
4510 if (lhs_type == rhs_type)
4515 return *lhs.m_value.array < *rhs.m_value.array;
4517 return *lhs.m_value.object < *rhs.m_value.object;
4521 return *lhs.m_value.string < *rhs.m_value.string;
4523 return lhs.m_value.boolean < rhs.m_value.boolean;
4525 return lhs.m_value.number_integer < rhs.m_value.number_integer;
4527 return lhs.m_value.number_float < rhs.m_value.number_float;
4535 rhs.m_value.number_float;
4539 return lhs.m_value.number_float <
4568 return not (rhs < lhs);
4590 return not (lhs <= rhs);
4612 return not (lhs < rhs);
4647 friend std::ostream&
operator<<(std::ostream& o,
const basic_json& j)
4650 const bool pretty_print = (o.width() > 0);
4651 const auto indentation = (pretty_print ? o.width() : 0);
4657 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
4665 friend std::ostream&
operator>>(
const basic_json& j, std::ostream& o)
4706 return parser(s, cb).
parse();
4735 return parser(i, cb).
parse();
4743 return parser(i, cb).
parse();
4771 j = parser(i).
parse();
4781 j = parser(i).
parse();
4823 static std::size_t extra_space(
const string_t& s) noexcept
4825 std::size_t result = 0;
4827 for (
const auto& c : s)
4846 if (c >= 0x00 and c <= 0x1f)
4874 const auto space = extra_space(s);
4881 string_t result(s.size() + space,
'\\');
4882 std::size_t pos = 0;
4884 for (
const auto& c : s)
4891 result[pos + 1] =
'"';
4907 result[pos + 1] =
'b';
4915 result[pos + 1] =
'f';
4923 result[pos + 1] =
'n';
4931 result[pos + 1] =
'r';
4939 result[pos + 1] =
't';
4946 if (c >= 0x00 and c <= 0x1f)
4949 auto hexify = [](
const char v) ->
char
4951 return (v < 10) ? (
'0' + v) : (
'a' + v - 10);
4956 {
'u',
'0',
'0', hexify(c >> 4), hexify(c & 0x0f)
4994 void dump(std::ostream& o,
4995 const bool pretty_print,
4996 const unsigned int indent_step,
4997 const unsigned int current_indent = 0)
const
5000 unsigned int new_indent = current_indent;
5006 if (m_value.object->empty())
5017 new_indent += indent_step;
5021 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5023 if (i != m_value.object->cbegin())
5025 o << (pretty_print ?
",\n" :
",");
5027 o <<
string_t(new_indent,
' ') <<
"\""
5028 << escape_string(i->first) <<
"\":"
5029 << (pretty_print ?
" " :
"");
5030 i->second.dump(o, pretty_print, indent_step, new_indent);
5036 new_indent -= indent_step;
5040 o <<
string_t(new_indent,
' ') +
"}";
5046 if (m_value.array->empty())
5057 new_indent += indent_step;
5061 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5063 if (i != m_value.array->cbegin())
5065 o << (pretty_print ?
",\n" :
",");
5068 i->dump(o, pretty_print, indent_step, new_indent);
5074 new_indent -= indent_step;
5078 o <<
string_t(new_indent,
' ') <<
"]";
5084 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
5090 o << (m_value.boolean ?
"true" :
"false");
5096 o << m_value.number_integer;
5105 o << std::setprecision(std::numeric_limits<number_float_t>::digits10) << m_value.number_float;
5132 json_value m_value = {};
5149 class primitive_iterator_t
5165 bool is_begin()
const
5167 return (m_it == begin_value);
5173 return (m_it == end_value);
5193 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5203 struct internal_iterator
5206 typename object_t::iterator object_iterator;
5208 typename array_t::iterator array_iterator;
5210 primitive_iterator_t primitive_iterator;
5214 : object_iterator(), array_iterator(), primitive_iterator()
5232 class const_iterator :
public std::iterator<std::random_access_iterator_tag, const basic_json>
5235 friend class basic_json;
5255 switch (m_object->m_type)
5259 m_it.object_iterator =
typename object_t::iterator();
5265 m_it.array_iterator =
typename array_t::iterator();
5271 m_it.primitive_iterator = primitive_iterator_t();
5280 switch (m_object->m_type)
5284 m_it.object_iterator = other.m_it.object_iterator;
5290 m_it.array_iterator = other.m_it.array_iterator;
5296 m_it.primitive_iterator = other.m_it.primitive_iterator;
5304 : m_object(other.m_object), m_it(other.m_it)
5309 std::is_nothrow_move_constructible<pointer>::value and
5310 std::is_nothrow_move_assignable<pointer>::value and
5311 std::is_nothrow_move_constructible<internal_iterator>::value and
5312 std::is_nothrow_move_assignable<internal_iterator>::value
5315 std::swap(m_object, other.m_object);
5316 std::swap(m_it, other.m_it);
5324 switch (m_object->m_type)
5328 m_it.object_iterator = m_object->m_value.object->begin();
5334 m_it.array_iterator = m_object->m_value.array->begin();
5341 m_it.primitive_iterator.set_end();
5347 m_it.primitive_iterator.set_begin();
5356 switch (m_object->m_type)
5360 m_it.object_iterator = m_object->m_value.object->end();
5366 m_it.array_iterator = m_object->m_value.array->end();
5372 m_it.primitive_iterator.set_end();
5382 switch (m_object->m_type)
5386 return m_it.object_iterator->second;
5391 return *m_it.array_iterator;
5396 throw std::out_of_range(
"cannot get value");
5401 return m_it.primitive_iterator.is_begin()
5403 :
throw std::out_of_range(
"cannot get value");
5411 switch (m_object->m_type)
5415 return &(m_it.object_iterator->second);
5420 return &*m_it.array_iterator;
5425 return m_it.primitive_iterator.is_begin()
5427 :
throw std::out_of_range(
"cannot get value");
5435 auto result = *
this;
5443 switch (m_object->m_type)
5447 ++m_it.object_iterator;
5453 ++m_it.array_iterator;
5459 ++m_it.primitive_iterator;
5470 auto result = *
this;
5478 switch (m_object->m_type)
5482 --m_it.object_iterator;
5488 --m_it.array_iterator;
5494 --m_it.primitive_iterator;
5506 if (m_object != other.m_object)
5508 throw std::domain_error(
"cannot compare iterators of different containers");
5511 switch (m_object->m_type)
5515 return (m_it.object_iterator == other.m_it.object_iterator);
5520 return (m_it.array_iterator == other.m_it.array_iterator);
5525 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
5540 if (m_object != other.m_object)
5542 throw std::domain_error(
"cannot compare iterators of different containers");
5545 switch (m_object->m_type)
5549 throw std::domain_error(
"cannot use operator< for object iterators");
5554 return (m_it.array_iterator < other.m_it.array_iterator);
5559 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
5567 return not other.operator < (*this);
5585 switch (m_object->m_type)
5589 throw std::domain_error(
"cannot use operator+= for object iterators");
5594 m_it.array_iterator += i;
5600 m_it.primitive_iterator += i;
5617 auto result = *
this;
5625 auto result = *
this;
5633 switch (m_object->m_type)
5637 throw std::domain_error(
"cannot use operator- for object iterators");
5642 return m_it.array_iterator - other.m_it.array_iterator;
5647 return m_it.primitive_iterator - other.m_it.primitive_iterator;
5655 switch (m_object->m_type)
5659 throw std::domain_error(
"cannot use operator[] for object iterators");
5664 return *(m_it.array_iterator + n);
5669 throw std::out_of_range(
"cannot get value");
5674 return (m_it.primitive_iterator == -n)
5676 :
throw std::out_of_range(
"cannot get value");
5682 typename object_t::key_type
key()
const
5684 return m_object->is_object()
5685 ? m_it.object_iterator->first
5686 :
throw std::domain_error(
"cannot use key() for non-object iterators");
5699 internal_iterator m_it = internal_iterator();
5735 std::is_nothrow_move_constructible<pointer>::value and
5736 std::is_nothrow_move_assignable<pointer>::value and
5737 std::is_nothrow_move_constructible<internal_iterator>::value and
5738 std::is_nothrow_move_assignable<internal_iterator>::value
5804 auto result = *
this;
5812 auto result = *
this;
5852 template<
typename Base>
5853 class json_reverse_iterator :
public std::reverse_iterator<Base>
5871 return base_iterator::operator++(1);
5877 base_iterator::operator++();
5884 return base_iterator::operator--(1);
5890 base_iterator::operator--();
5897 base_iterator::operator+=(i);
5904 auto result = *
this;
5912 auto result = *
this;
5920 return this->base() - other.base();
5930 typename object_t::key_type
key()
const
5932 auto it = --this->base();
5939 auto it = --this->base();
5940 return it.operator * ();
5955 basic_json& container;
5957 using json_iterator = decltype(std::begin(container));
5960 class iterator_wrapper_internal
5964 json_iterator anchor;
5966 size_t array_index = 0;
5970 iterator_wrapper_internal(json_iterator i) : anchor(i)
5974 iterator_wrapper_internal& operator*()
5980 iterator_wrapper_internal& operator++()
5989 bool operator!= (
const iterator_wrapper_internal& o)
5991 return anchor != o.anchor;
5997 switch (anchor.m_object->type())
6002 return std::to_string(array_index);
6008 return anchor.key();
6020 typename json_iterator::reference
value()
const
6022 return anchor.value();
6035 return iterator_wrapper_internal(container.
begin());
6039 iterator_wrapper_internal
end()
6041 return iterator_wrapper_internal(container.
end());
6061 enum class token_type
6080 using lexer_char_t =
unsigned char;
6083 explicit lexer(
const string_t& s) noexcept
6084 : m_stream(
nullptr), m_buffer(s)
6086 m_content =
reinterpret_cast<const lexer_char_t*
>(s.c_str());
6087 m_start = m_cursor = m_content;
6088 m_limit = m_content + s.size();
6090 explicit lexer(std::istream* s) noexcept
6091 : m_stream(s), m_buffer()
6093 getline(*m_stream, m_buffer);
6094 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
6095 m_start = m_cursor = m_content;
6096 m_limit = m_content + m_buffer.size();
6103 lexer(
const lexer&) =
delete;
6117 static string_t to_unicode(
const std::size_t codepoint1,
6118 const std::size_t codepoint2 = 0)
6123 std::size_t codepoint = codepoint1;
6126 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6129 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6143 throw std::invalid_argument(
"missing or wrong low surrogate");
6147 if (codepoint < 0x80)
6150 result.append(1, static_cast<typename string_t::value_type>(codepoint));
6152 else if (codepoint <= 0x7ff)
6155 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
6156 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6158 else if (codepoint <= 0xffff)
6161 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
6162 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6163 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6165 else if (codepoint <= 0x10ffff)
6168 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
6169 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
6170 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6171 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6175 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
6182 static std::string token_type_name(token_type t)
6186 case token_type::uninitialized:
6187 return "<uninitialized>";
6188 case token_type::literal_true:
6189 return "true literal";
6190 case token_type::literal_false:
6191 return "false literal";
6192 case token_type::literal_null:
6193 return "null literal";
6194 case token_type::value_string:
6195 return "string literal";
6196 case token_type::value_number:
6197 return "number literal";
6198 case token_type::begin_array:
6200 case token_type::begin_object:
6202 case token_type::end_array:
6204 case token_type::end_object:
6206 case token_type::name_separator:
6208 case token_type::value_separator:
6210 case token_type::end_of_input:
6211 return "<end of input>";
6212 case token_type::parse_error:
6213 return "<parse error>";
6227 token_type scan() noexcept
6238 unsigned int yyaccept = 0;
6239 static const unsigned char yybm[] =
6241 0, 0, 0, 0, 0, 0, 0, 0,
6242 0, 32, 32, 0, 0, 32, 0, 0,
6243 64, 64, 64, 64, 64, 64, 64, 64,
6244 64, 64, 64, 64, 64, 64, 64, 64,
6245 96, 64, 0, 64, 64, 64, 64, 64,
6246 64, 64, 64, 64, 64, 64, 64, 64,
6247 192, 192, 192, 192, 192, 192, 192, 192,
6248 192, 192, 64, 64, 64, 64, 64, 64,
6249 64, 64, 64, 64, 64, 64, 64, 64,
6250 64, 64, 64, 64, 64, 64, 64, 64,
6251 64, 64, 64, 64, 64, 64, 64, 64,
6252 64, 64, 64, 64, 0, 64, 64, 64,
6253 64, 64, 64, 64, 64, 64, 64, 64,
6254 64, 64, 64, 64, 64, 64, 64, 64,
6255 64, 64, 64, 64, 64, 64, 64, 64,
6256 64, 64, 64, 64, 64, 64, 64, 64,
6257 64, 64, 64, 64, 64, 64, 64, 64,
6258 64, 64, 64, 64, 64, 64, 64, 64,
6259 64, 64, 64, 64, 64, 64, 64, 64,
6260 64, 64, 64, 64, 64, 64, 64, 64,
6261 64, 64, 64, 64, 64, 64, 64, 64,
6262 64, 64, 64, 64, 64, 64, 64, 64,
6263 64, 64, 64, 64, 64, 64, 64, 64,
6264 64, 64, 64, 64, 64, 64, 64, 64,
6265 64, 64, 64, 64, 64, 64, 64, 64,
6266 64, 64, 64, 64, 64, 64, 64, 64,
6267 64, 64, 64, 64, 64, 64, 64, 64,
6268 64, 64, 64, 64, 64, 64, 64, 64,
6269 64, 64, 64, 64, 64, 64, 64, 64,
6270 64, 64, 64, 64, 64, 64, 64, 64,
6271 64, 64, 64, 64, 64, 64, 64, 64,
6272 64, 64, 64, 64, 64, 64, 64, 64,
6274 if ((m_limit - m_cursor) < 5)
6287 goto basic_json_parser_28;
6291 goto basic_json_parser_30;
6295 goto basic_json_parser_4;
6302 goto basic_json_parser_2;
6306 goto basic_json_parser_30;
6316 goto basic_json_parser_27;
6320 goto basic_json_parser_30;
6322 goto basic_json_parser_16;
6330 goto basic_json_parser_23;
6332 goto basic_json_parser_30;
6338 goto basic_json_parser_24;
6342 goto basic_json_parser_26;
6344 goto basic_json_parser_18;
6357 goto basic_json_parser_8;
6361 goto basic_json_parser_30;
6363 goto basic_json_parser_10;
6369 goto basic_json_parser_22;
6373 goto basic_json_parser_30;
6375 goto basic_json_parser_20;
6384 goto basic_json_parser_21;
6388 goto basic_json_parser_30;
6390 goto basic_json_parser_12;
6398 goto basic_json_parser_30;
6400 goto basic_json_parser_14;
6406 goto basic_json_parser_6;
6408 goto basic_json_parser_30;
6413 basic_json_parser_2:
6416 goto basic_json_parser_5;
6417 basic_json_parser_3:
6421 basic_json_parser_4:
6423 if (m_limit <= m_cursor)
6428 basic_json_parser_5:
6429 if (yybm[0 + yych] & 32)
6431 goto basic_json_parser_4;
6433 goto basic_json_parser_3;
6434 basic_json_parser_6:
6436 yych = *(m_marker = ++m_cursor);
6439 goto basic_json_parser_64;
6441 basic_json_parser_7:
6443 return token_type::parse_error;
6445 basic_json_parser_8:
6448 return token_type::begin_array;
6450 basic_json_parser_10:
6453 return token_type::end_array;
6455 basic_json_parser_12:
6458 return token_type::begin_object;
6460 basic_json_parser_14:
6463 return token_type::end_object;
6465 basic_json_parser_16:
6468 return token_type::value_separator;
6470 basic_json_parser_18:
6473 return token_type::name_separator;
6475 basic_json_parser_20:
6477 yych = *(m_marker = ++m_cursor);
6480 goto basic_json_parser_60;
6482 goto basic_json_parser_7;
6483 basic_json_parser_21:
6485 yych = *(m_marker = ++m_cursor);
6488 goto basic_json_parser_56;
6490 goto basic_json_parser_7;
6491 basic_json_parser_22:
6493 yych = *(m_marker = ++m_cursor);
6496 goto basic_json_parser_51;
6498 goto basic_json_parser_7;
6499 basic_json_parser_23:
6503 goto basic_json_parser_7;
6507 goto basic_json_parser_50;
6511 goto basic_json_parser_41;
6513 goto basic_json_parser_7;
6514 basic_json_parser_24:
6516 yych = *(m_marker = ++m_cursor);
6521 goto basic_json_parser_43;
6528 goto basic_json_parser_44;
6532 goto basic_json_parser_44;
6535 basic_json_parser_25:
6537 return token_type::value_number;
6539 basic_json_parser_26:
6541 yych = *(m_marker = ++m_cursor);
6542 goto basic_json_parser_42;
6543 basic_json_parser_27:
6545 yych = *(m_marker = ++m_cursor);
6548 goto basic_json_parser_7;
6550 goto basic_json_parser_32;
6551 basic_json_parser_28:
6554 return token_type::end_of_input;
6556 basic_json_parser_30:
6558 goto basic_json_parser_7;
6559 basic_json_parser_31:
6561 if (m_limit <= m_cursor)
6566 basic_json_parser_32:
6567 if (yybm[0 + yych] & 64)
6569 goto basic_json_parser_31;
6573 goto basic_json_parser_33;
6577 goto basic_json_parser_35;
6579 goto basic_json_parser_34;
6580 basic_json_parser_33:
6581 m_cursor = m_marker;
6584 goto basic_json_parser_7;
6588 goto basic_json_parser_25;
6590 basic_json_parser_34:
6592 if (m_limit <= m_cursor)
6603 goto basic_json_parser_31;
6607 goto basic_json_parser_33;
6609 goto basic_json_parser_31;
6617 goto basic_json_parser_33;
6619 goto basic_json_parser_31;
6625 goto basic_json_parser_31;
6627 goto basic_json_parser_33;
6637 goto basic_json_parser_31;
6641 goto basic_json_parser_31;
6643 goto basic_json_parser_33;
6651 goto basic_json_parser_31;
6653 goto basic_json_parser_33;
6659 goto basic_json_parser_31;
6663 goto basic_json_parser_37;
6665 goto basic_json_parser_33;
6669 basic_json_parser_35:
6672 return token_type::value_string;
6674 basic_json_parser_37:
6676 if (m_limit <= m_cursor)
6685 goto basic_json_parser_33;
6689 goto basic_json_parser_33;
6696 goto basic_json_parser_38;
6700 goto basic_json_parser_33;
6704 goto basic_json_parser_33;
6707 basic_json_parser_38:
6709 if (m_limit <= m_cursor)
6718 goto basic_json_parser_33;
6722 goto basic_json_parser_33;
6729 goto basic_json_parser_39;
6733 goto basic_json_parser_33;
6737 goto basic_json_parser_33;
6740 basic_json_parser_39:
6742 if (m_limit <= m_cursor)
6751 goto basic_json_parser_33;
6755 goto basic_json_parser_33;
6762 goto basic_json_parser_40;
6766 goto basic_json_parser_33;
6770 goto basic_json_parser_33;
6773 basic_json_parser_40:
6775 if (m_limit <= m_cursor)
6784 goto basic_json_parser_33;
6788 goto basic_json_parser_31;
6790 goto basic_json_parser_33;
6796 goto basic_json_parser_31;
6800 goto basic_json_parser_33;
6804 goto basic_json_parser_31;
6806 goto basic_json_parser_33;
6808 basic_json_parser_41:
6810 m_marker = ++m_cursor;
6811 if ((m_limit - m_cursor) < 3)
6816 basic_json_parser_42:
6817 if (yybm[0 + yych] & 128)
6819 goto basic_json_parser_41;
6825 goto basic_json_parser_25;
6832 goto basic_json_parser_44;
6836 goto basic_json_parser_44;
6838 goto basic_json_parser_25;
6840 basic_json_parser_43:
6844 goto basic_json_parser_33;
6848 goto basic_json_parser_48;
6850 goto basic_json_parser_33;
6851 basic_json_parser_44:
6857 goto basic_json_parser_33;
6864 goto basic_json_parser_45;
6868 goto basic_json_parser_33;
6872 goto basic_json_parser_46;
6874 goto basic_json_parser_33;
6876 basic_json_parser_45:
6880 goto basic_json_parser_33;
6884 goto basic_json_parser_33;
6886 basic_json_parser_46:
6888 if (m_limit <= m_cursor)
6895 goto basic_json_parser_25;
6899 goto basic_json_parser_46;
6901 goto basic_json_parser_25;
6902 basic_json_parser_48:
6904 m_marker = ++m_cursor;
6905 if ((m_limit - m_cursor) < 3)
6914 goto basic_json_parser_25;
6918 goto basic_json_parser_48;
6920 goto basic_json_parser_25;
6926 goto basic_json_parser_44;
6930 goto basic_json_parser_44;
6932 goto basic_json_parser_25;
6934 basic_json_parser_50:
6936 yych = *(m_marker = ++m_cursor);
6941 goto basic_json_parser_43;
6943 goto basic_json_parser_25;
6949 goto basic_json_parser_44;
6953 goto basic_json_parser_44;
6955 goto basic_json_parser_25;
6957 basic_json_parser_51:
6961 goto basic_json_parser_33;
6966 goto basic_json_parser_33;
6971 goto basic_json_parser_33;
6975 return token_type::literal_false;
6977 basic_json_parser_56:
6981 goto basic_json_parser_33;
6986 goto basic_json_parser_33;
6990 return token_type::literal_true;
6992 basic_json_parser_60:
6996 goto basic_json_parser_33;
7001 goto basic_json_parser_33;
7005 return token_type::literal_null;
7007 basic_json_parser_64:
7011 goto basic_json_parser_33;
7023 void yyfill() noexcept
7025 if (not m_stream or not * m_stream)
7030 const ssize_t offset_start = m_start - m_content;
7031 const ssize_t offset_marker = m_marker - m_start;
7032 const ssize_t offset_cursor = m_cursor - m_start;
7034 m_buffer.erase(0, static_cast<size_t>(offset_start));
7036 std::getline(*m_stream, line);
7037 m_buffer +=
"\n" + line;
7039 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
7040 m_start = m_content;
7041 m_marker = m_start + offset_marker;
7042 m_cursor = m_start + offset_cursor;
7043 m_limit = m_start + m_buffer.size() - 1;
7047 string_t get_token() const noexcept
7049 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7050 static_cast<size_t>(m_cursor - m_start));
7077 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7080 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7136 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7137 4).c_str(),
nullptr, 16);
7140 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7143 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
7145 throw std::invalid_argument(
"missing low surrogate");
7149 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7150 (i + 7), 4).c_str(),
nullptr, 16);
7151 result += to_unicode(codepoint, codepoint2);
7158 result += to_unicode(codepoint);
7170 result.append(1, static_cast<typename string_t::value_type>(*i));
7194 long double get_number()
const
7197 typename string_t::value_type* endptr;
7198 const auto float_val = std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start),
7203 return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
7208 std::istream* m_stream;
7212 const lexer_char_t* m_content =
nullptr;
7214 const lexer_char_t* m_start =
nullptr;
7216 const lexer_char_t* m_marker =
nullptr;
7218 const lexer_char_t* m_cursor =
nullptr;
7220 const lexer_char_t* m_limit =
nullptr;
7233 : callback(cb), m_lexer(s)
7241 : callback(cb), m_lexer(&_is)
7250 basic_json result = parse_internal(
true);
7252 expect(lexer::token_type::end_of_input);
7256 return result.is_discarded() ?
basic_json() : result;
7261 basic_json parse_internal(
bool keep)
7267 case lexer::token_type::begin_object:
7280 if (last_token == lexer::token_type::end_object)
7291 unexpect(lexer::token_type::value_separator);
7297 if (last_token == lexer::token_type::value_separator)
7303 expect(lexer::token_type::value_string);
7304 const auto key = m_lexer.get_string();
7306 bool keep_tag =
false;
7322 expect(lexer::token_type::name_separator);
7326 auto value = parse_internal(keep);
7327 if (keep and keep_tag and not
value.is_discarded())
7329 result[key] = std::move(
value);
7332 while (last_token == lexer::token_type::value_separator);
7335 expect(lexer::token_type::end_object);
7345 case lexer::token_type::begin_array:
7358 if (last_token == lexer::token_type::end_array)
7369 unexpect(lexer::token_type::value_separator);
7375 if (last_token == lexer::token_type::value_separator)
7381 auto value = parse_internal(keep);
7382 if (keep and not
value.is_discarded())
7384 result.push_back(std::move(
value));
7387 while (last_token == lexer::token_type::value_separator);
7390 expect(lexer::token_type::end_array);
7400 case lexer::token_type::literal_null:
7407 case lexer::token_type::value_string:
7409 const auto s = m_lexer.get_string();
7415 case lexer::token_type::literal_true:
7419 result.m_value =
true;
7423 case lexer::token_type::literal_false:
7427 result.m_value =
false;
7431 case lexer::token_type::value_number:
7433 auto float_val = m_lexer.get_number();
7437 if (std::isnan(float_val))
7439 throw std::invalid_argument(std::string(
"parse error - ") +
7440 m_lexer.get_token() +
" is not a number");
7447 if (approx(float_val, static_cast<long double>(int_val)))
7451 result.m_value = int_val;
7465 unexpect(last_token);
7477 typename lexer::token_type get_token()
7479 last_token = m_lexer.scan();
7483 void expect(
typename lexer::token_type t)
const
7485 if (t != last_token)
7487 std::string error_msg =
"parse error - unexpected \'";
7488 error_msg += m_lexer.get_token();
7489 error_msg +=
"\' (" + lexer::token_type_name(last_token);
7490 error_msg +=
"); expected " + lexer::token_type_name(t);
7491 throw std::invalid_argument(error_msg);
7495 void unexpect(
typename lexer::token_type t)
const
7497 if (t == last_token)
7499 std::string error_msg =
"parse error - unexpected \'";
7500 error_msg += m_lexer.get_token();
7501 error_msg +=
"\' (";
7502 error_msg += lexer::token_type_name(last_token) +
")";
7503 throw std::invalid_argument(error_msg);
7513 typename lexer::token_type last_token = lexer::token_type::uninitialized;
7551 is_nothrow_move_constructible<nlohmann::json>::value and
7552 is_nothrow_move_assignable<nlohmann::json>::value
7570 const auto& h = hash<nlohmann::json::string_t>();
7588 inline nlohmann::json operator "" _json(
const char* s, std::size_t)
7591 (const_cast<char*>(s)));
basic_json(const number_float_t value)
create a floating-point number (explicit)
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 operator++(int)
post-increment (it++)
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
iterator insert(const_iterator pos, basic_json &&value)
inserts element
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
basic_json(const int value)
create an integer number from an enum type (explicit)
json_reverse_iterator operator--(int)
post-decrement (it–)
StringType string_t
a type for a string
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
reference operator+=(const typename object_t::value_type &value)
add an object to an object
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)
void push_back(const typename object_t::value_type &value)
add an object to an object
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
const_iterator cbegin() const
returns a const iterator to the first element
basic_json(const CompatibleObjectType &value)
create an object (implicit)
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)
the parser read ] and finished processing a JSON array
const_iterator base_iterator
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
iterator insert(const_iterator pos, size_type count, const basic_json &value)
inserts elements
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
reference operator+=(const basic_json &value)
add an object to an array
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
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
basic_json(const CompatibleArrayType &value)
create an array (implicit)
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
AllocatorType< basic_json > allocator_type
the allocator type
bool is_number_integer() const noexcept
return whether value is an integer number
basic_json(const string_t &value)
create a string (explicit)
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
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
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
basic_json(size_type count, const basic_json &value)
construct an array with count copies of given 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
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
reference operator+=(basic_json &&value)
add an object to an array
const_reverse_iterator rbegin() const
returns a const reverse iterator to the last element
basic_json(const array_t &value)
create an array (explicit)
basic_json(const basic_json &other)
copy constructor
const_iterator operator+(difference_type i)
add to iterator
basic_json(boolean_t value)
create a boolean (explicit)
value_t
the JSON type enumeration
const value_type & const_reference
the type of an element const reference
basic_json(const CompatibleNumberFloatType value) noexcept
create an floating-point 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
void push_back(basic_json &&value)
add an object to an array
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
basic_json(const CompatibleStringType &value)
create a string (implicit)
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
basic_json(const object_t &value)
create an object (explicit)
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
number value (floating-point)
basic_json(const CompatibleNumberIntegerType value) noexcept
create an integer number (implicit)
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)
void push_back(const basic_json &value)
add an object to an array
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
basic_json(const typename string_t::value_type *value)
create a string (explicit)
bool operator<=(const const_iterator &other) const
comparison: less than or equal
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
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
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
basic_json(const value_t value)
create an empty value with a given type
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
iterator insert(const_iterator pos, const basic_json &value)
inserts element
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
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