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
1378 bool type_deduction =
true,
1382 bool is_an_object =
true;
1386 for (
const auto& element : init)
1388 if (not element.is_array() or element.size() != 2
1389 or not element[0].is_string())
1393 is_an_object =
false;
1399 if (not type_deduction)
1404 is_an_object =
false;
1410 throw std::domain_error(
"cannot create object from initializer list");
1420 for (
auto& element : init)
1422 m_value.object->emplace(std::move(*(element[0].m_value.string)), std::move(element[1]));
1429 m_value.array = create<array_t>(std::move(init));
1467 static basic_json
array(std::initializer_list<basic_json> init =
1468 std::initializer_list<basic_json>())
1507 static basic_json
object(std::initializer_list<basic_json> init =
1508 std::initializer_list<basic_json>())
1534 m_value.array = create<array_t>(cnt, val);
1571 template <
class InputIT,
typename
1573 std::is_same<InputIT, typename basic_json_t::iterator>::value or
1574 std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1577 basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1580 if (first.m_object != last.m_object)
1582 throw std::domain_error(
"iterators are not compatible");
1593 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1595 throw std::out_of_range(
"iterators out of range");
1610 m_value.number_integer = first.m_object->m_value.number_integer;
1616 m_value.number_float = first.m_object->m_value.number_float;
1622 m_value.boolean = first.m_object->m_value.boolean;
1628 m_value = *first.m_object->m_value.string;
1634 m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1640 m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1646 throw std::domain_error(
"cannot use construct with iterators from " + first.m_object->type_name());
1676 : m_type(other.m_type)
1682 m_value = *other.m_value.object;
1688 m_value = *other.m_value.array;
1694 m_value = *other.m_value.string;
1700 m_value = other.m_value.boolean;
1706 m_value = other.m_value.number_integer;
1712 m_value = other.m_value.number_float;
1742 : m_type(
std::move(other.m_type)),
1743 m_value(
std::move(other.m_value))
1772 std::is_nothrow_move_constructible<value_t>::value and
1773 std::is_nothrow_move_assignable<value_t>::value and
1774 std::is_nothrow_move_constructible<json_value>::value and
1775 std::is_nothrow_move_assignable<json_value>::value
1779 swap(m_type, other.m_type);
1780 swap(m_value, other.m_value);
1803 AllocatorType<object_t> alloc;
1804 alloc.destroy(m_value.object);
1805 alloc.deallocate(m_value.object, 1);
1811 AllocatorType<array_t> alloc;
1812 alloc.destroy(m_value.array);
1813 alloc.deallocate(m_value.array, 1);
1819 AllocatorType<string_t> alloc;
1820 alloc.destroy(m_value.string);
1821 alloc.deallocate(m_value.string, 1);
1868 std::stringstream ss;
1872 dump(ss,
true, static_cast<unsigned int>(indent));
2160 template <
class T,
typename
2162 std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2163 std::is_convertible<basic_json_t, typename T::mapped_type>::value
2165 T get_impl(T*)
const
2169 return T(m_value.object->begin(), m_value.object->end());
2173 throw std::domain_error(
"type must be object, but is " + type_name());
2182 return *(m_value.object);
2186 throw std::domain_error(
"type must be object, but is " + type_name());
2191 template <
class T,
typename
2193 std::is_convertible<basic_json_t, typename T::value_type>::value and
2194 not std::is_same<basic_json_t, typename T::value_type>::value and
2195 not std::is_arithmetic<T>::value and
2196 not std::is_convertible<std::string, T>::value and
2197 not has_mapped_type<T>::value
2199 T get_impl(T*)
const
2204 std::transform(m_value.array->begin(), m_value.array->end(),
2205 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2207 return i.get<
typename T::value_type>();
2213 throw std::domain_error(
"type must be array, but is " + type_name());
2218 template <
class T,
typename
2220 std::is_convertible<basic_json_t, T>::value and
2221 not std::is_same<basic_json_t, T>::value
2223 std::vector<T> get_impl(std::vector<T>*)
const
2227 std::vector<T> to_vector;
2228 to_vector.reserve(m_value.array->size());
2229 std::transform(m_value.array->begin(), m_value.array->end(),
2230 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2238 throw std::domain_error(
"type must be array, but is " + type_name());
2243 template <
class T,
typename
2245 std::is_same<basic_json, typename T::value_type>::value and
2246 not has_mapped_type<T>::value
2248 T get_impl(T*)
const
2252 return T(m_value.array->begin(), m_value.array->end());
2256 throw std::domain_error(
"type must be array, but is " + type_name());
2265 return *(m_value.array);
2269 throw std::domain_error(
"type must be array, but is " + type_name());
2274 template <
typename T,
typename
2276 std::is_convertible<string_t, T>::value
2278 T get_impl(T*)
const
2282 return *m_value.string;
2286 throw std::domain_error(
"type must be string, but is " + type_name());
2291 template<
typename T,
typename
2293 std::is_arithmetic<T>::value
2295 T get_impl(T*)
const
2301 return static_cast<T
>(m_value.number_integer);
2306 return static_cast<T
>(m_value.number_float);
2311 throw std::domain_error(
"type must be number, but is " + type_name());
2321 return m_value.boolean;
2325 throw std::domain_error(
"type must be boolean, but is " + type_name());
2332 return is_object() ? m_value.object :
nullptr;
2338 return is_object() ? m_value.object :
nullptr;
2344 return is_array() ? m_value.array :
nullptr;
2350 return is_array() ? m_value.array :
nullptr;
2356 return is_string() ? m_value.string :
nullptr;
2362 return is_string() ? m_value.string :
nullptr;
2368 return is_boolean() ? &m_value.boolean :
nullptr;
2374 return is_boolean() ? &m_value.boolean :
nullptr;
2439 template<
typename ValueType,
typename
2441 not std::is_pointer<ValueType>::value
2443 ValueType
get()
const
2445 return get_impl(static_cast<ValueType*>(
nullptr));
2474 template<
typename PointerType,
typename
2476 std::is_pointer<PointerType>::value
2478 PointerType
get() noexcept
2481 return get_ptr<PointerType>();
2488 template<
typename PointerType,
typename
2490 std::is_pointer<PointerType>::value
2492 const PointerType
get()
const noexcept
2495 return get_ptr<PointerType>();
2523 template<
typename PointerType,
typename
2525 std::is_pointer<PointerType>::value
2530 return get_impl_ptr(static_cast<PointerType>(
nullptr));
2537 template<
typename PointerType,
typename
2539 std::is_pointer<PointerType>::value
2540 and std::is_const<typename std::remove_pointer<PointerType>::type>
::value
2545 return get_impl_ptr(static_cast<const PointerType>(
nullptr));
2576 template<
typename ValueType,
typename
2578 not std::is_pointer<ValueType>::value
2579 and not std::is_same<ValueType, typename string_t::value_type>::value
2580 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>
::value
2582 operator ValueType()
const
2585 return get<ValueType>();
2627 return m_value.array->at(idx);
2629 catch (std::out_of_range& e)
2632 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
2637 throw std::domain_error(
"cannot use at() with " + type_name());
2670 return m_value.array->at(idx);
2672 catch (std::out_of_range& e)
2675 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
2680 throw std::domain_error(
"cannot use at() with " + type_name());
2717 return m_value.object->at(key);
2719 catch (std::out_of_range& e)
2722 throw std::out_of_range(
"key '" + key +
"' not found");
2727 throw std::domain_error(
"cannot use at() with " + type_name());
2764 return m_value.object->at(key);
2766 catch (std::out_of_range& e)
2769 throw std::out_of_range(
"key '" + key +
"' not found");
2774 throw std::domain_error(
"cannot use at() with " + type_name());
2809 m_value.array = create<array_t>();
2815 for (
size_t i = m_value.array->size(); i <= idx; ++i)
2820 return m_value.array->operator[](idx);
2824 throw std::domain_error(
"cannot use operator[] with " + type_name());
2852 return m_value.array->operator[](idx);
2856 throw std::domain_error(
"cannot use operator[] with " + type_name());
2893 m_value.object = create<object_t>();
2899 return m_value.object->operator[](key);
2903 throw std::domain_error(
"cannot use operator[] with " + type_name());
2939 return m_value.object->find(key)->second;
2943 throw std::domain_error(
"cannot use operator[] with " + type_name());
2976 template<
typename T, std::
size_t n>
2989 return m_value.object->operator[](key);
2993 throw std::domain_error(
"cannot use operator[] with " + type_name());
3026 template<
typename T, std::
size_t n>
3032 return m_value.object->find(key)->second;
3036 throw std::domain_error(
"cannot use operator[] with " + type_name());
3088 template <
class ValueType,
typename
3090 std::is_convertible<basic_json_t, ValueType>::value
3092 ValueType
value(
const typename object_t::key_type& key, ValueType default_value)
const
3098 const auto it =
find(key);
3105 return default_value;
3110 throw std::domain_error(
"cannot use value() with " + type_name());
3118 string_t value(
const typename object_t::key_type& key,
const char* default_value)
const
3238 template <
class InteratorType,
typename
3240 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3241 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3247 if (
this != pos.m_object)
3249 throw std::domain_error(
"iterator does not fit current value");
3252 InteratorType result =
end();
3261 if (not pos.m_it.primitive_iterator.is_begin())
3263 throw std::out_of_range(
"iterator out of range");
3268 delete m_value.string;
3269 m_value.string =
nullptr;
3278 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3284 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3290 throw std::domain_error(
"cannot use erase() with " + type_name());
3341 template <
class InteratorType,
typename
3343 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3344 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3347 InteratorType
erase(InteratorType first, InteratorType last)
3350 if (
this != first.m_object or
this != last.m_object)
3352 throw std::domain_error(
"iterators do not fit current value");
3355 InteratorType result =
end();
3364 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3366 throw std::out_of_range(
"iterators out of range");
3371 delete m_value.string;
3372 m_value.string =
nullptr;
3381 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3382 last.m_it.object_iterator);
3388 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3389 last.m_it.array_iterator);
3395 throw std::domain_error(
"cannot use erase() with " + type_name());
3433 return m_value.object->erase(key);
3437 throw std::domain_error(
"cannot use erase() with " + type_name());
3472 throw std::out_of_range(
"index out of range");
3475 m_value.array->erase(m_value.array->begin() +
static_cast<difference_type>(idx));
3479 throw std::domain_error(
"cannot use erase() with " + type_name());
3502 auto result =
end();
3506 result.m_it.object_iterator = m_value.object->find(key);
3518 auto result =
cend();
3522 result.m_it.object_iterator = m_value.object->find(key);
3549 return is_object() ? m_value.object->count(key) : 0;
3789 template<
typename IteratorType>
class iteration_proxy;
3805 return iteration_proxy<iterator>(cont);
3813 return iteration_proxy<const_iterator>(cont);
3867 return m_value.array->empty();
3872 return m_value.object->empty();
3923 return m_value.array->size();
3928 return m_value.object->size();
3977 return m_value.array->max_size();
3982 return m_value.object->max_size();
4034 m_value.number_integer = 0;
4040 m_value.number_float = 0.0;
4046 m_value.boolean =
false;
4052 m_value.string->clear();
4058 m_value.array->clear();
4064 m_value.object->clear();
4100 throw std::domain_error(
"cannot use push_back() with " + type_name());
4111 m_value.array->push_back(std::move(val));
4135 throw std::domain_error(
"cannot use push_back() with " + type_name());
4146 m_value.array->push_back(val);
4184 throw std::domain_error(
"cannot use push_back() with " + type_name());
4195 m_value.object->insert(val);
4236 if (pos.m_object !=
this)
4238 throw std::domain_error(
"iterator does not fit current value");
4243 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4248 throw std::domain_error(
"cannot use insert() with " + type_name());
4291 if (pos.m_object !=
this)
4293 throw std::domain_error(
"iterator does not fit current value");
4298 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4303 throw std::domain_error(
"cannot use insert() with " + type_name());
4342 throw std::domain_error(
"cannot use insert() with " + type_name());
4346 if (pos.m_object !=
this)
4348 throw std::domain_error(
"iterator does not fit current value");
4351 if (first.m_object != last.m_object)
4353 throw std::domain_error(
"iterators do not fit");
4356 if (first.m_object ==
this or last.m_object ==
this)
4358 throw std::domain_error(
"passed iterators may not belong to container");
4363 result.m_it.array_iterator = m_value.array->insert(
4364 pos.m_it.array_iterator,
4365 first.m_it.array_iterator,
4366 last.m_it.array_iterator);
4399 throw std::domain_error(
"cannot use insert() with " + type_name());
4403 if (pos.m_object !=
this)
4405 throw std::domain_error(
"iterator does not fit current value");
4410 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4432 std::is_nothrow_move_constructible<value_t>::value and
4433 std::is_nothrow_move_assignable<value_t>::value and
4434 std::is_nothrow_move_constructible<json_value>::value and
4435 std::is_nothrow_move_assignable<json_value>::value
4438 std::swap(m_type, other.m_type);
4439 std::swap(m_value, other.m_value);
4467 std::swap(*(m_value.array), other);
4471 throw std::domain_error(
"cannot use swap() with " + type_name());
4500 std::swap(*(m_value.object), other);
4504 throw std::domain_error(
"cannot use swap() with " + type_name());
4533 std::swap(*(m_value.string), other);
4537 throw std::domain_error(
"cannot use swap() with " + type_name());
4563 static constexpr std::array<uint8_t, 7> order = {{
4580 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
4609 const auto lhs_type = lhs.type();
4610 const auto rhs_type = rhs.type();
4612 if (lhs_type == rhs_type)
4617 return *lhs.m_value.array == *rhs.m_value.array;
4619 return *lhs.m_value.object == *rhs.m_value.object;
4623 return *lhs.m_value.string == *rhs.m_value.string;
4625 return lhs.m_value.boolean == rhs.m_value.boolean;
4627 return lhs.m_value.number_integer == rhs.m_value.number_integer;
4629 return approx(lhs.m_value.number_float, rhs.m_value.number_float);
4636 return approx(static_cast<number_float_t>(lhs.m_value.number_integer),
4637 rhs.m_value.number_float);
4641 return approx(lhs.m_value.number_float,
4642 static_cast<number_float_t>(rhs.m_value.number_integer));
4697 return not (lhs == rhs);
4729 return not v.is_null();
4758 const auto lhs_type = lhs.type();
4759 const auto rhs_type = rhs.type();
4761 if (lhs_type == rhs_type)
4766 return *lhs.m_value.array < *rhs.m_value.array;
4768 return *lhs.m_value.object < *rhs.m_value.object;
4772 return *lhs.m_value.string < *rhs.m_value.string;
4774 return lhs.m_value.boolean < rhs.m_value.boolean;
4776 return lhs.m_value.number_integer < rhs.m_value.number_integer;
4778 return lhs.m_value.number_float < rhs.m_value.number_float;
4786 rhs.m_value.number_float;
4790 return lhs.m_value.number_float <
4819 return not (rhs < lhs);
4841 return not (lhs <= rhs);
4863 return not (lhs < rhs);
4898 friend std::ostream&
operator<<(std::ostream& o,
const basic_json& j)
4901 const bool pretty_print = (o.width() > 0);
4902 const auto indentation = (pretty_print ? o.width() : 0);
4908 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
4916 friend std::ostream&
operator>>(
const basic_json& j, std::ostream& o)
4957 return parser(s, cb).
parse();
4986 return parser(i, cb).
parse();
4994 return parser(i, cb).
parse();
5022 j = parser(i).
parse();
5032 j = parser(i).
parse();
5074 static std::size_t extra_space(
const string_t& s) noexcept
5076 std::size_t result = 0;
5078 for (
const auto& c : s)
5097 if (c >= 0x00 and c <= 0x1f)
5125 const auto space = extra_space(s);
5132 string_t result(s.size() + space,
'\\');
5133 std::size_t pos = 0;
5135 for (
const auto& c : s)
5142 result[pos + 1] =
'"';
5158 result[pos + 1] =
'b';
5166 result[pos + 1] =
'f';
5174 result[pos + 1] =
'n';
5182 result[pos + 1] =
'r';
5190 result[pos + 1] =
't';
5197 if (c >= 0x00 and c <= 0x1f)
5200 auto hexify = [](
const char v) ->
char
5202 return (v < 10) ? (
'0' + v) : (
'a' + v - 10);
5207 {
'u',
'0',
'0', hexify(c >> 4), hexify(c & 0x0f)
5245 void dump(std::ostream& o,
5246 const bool pretty_print,
5247 const unsigned int indent_step,
5248 const unsigned int current_indent = 0)
const
5251 unsigned int new_indent = current_indent;
5257 if (m_value.object->empty())
5268 new_indent += indent_step;
5272 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5274 if (i != m_value.object->cbegin())
5276 o << (pretty_print ?
",\n" :
",");
5278 o <<
string_t(new_indent,
' ') <<
"\""
5279 << escape_string(i->first) <<
"\":"
5280 << (pretty_print ?
" " :
"");
5281 i->second.dump(o, pretty_print, indent_step, new_indent);
5287 new_indent -= indent_step;
5291 o <<
string_t(new_indent,
' ') +
"}";
5297 if (m_value.array->empty())
5308 new_indent += indent_step;
5312 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5314 if (i != m_value.array->cbegin())
5316 o << (pretty_print ?
",\n" :
",");
5319 i->dump(o, pretty_print, indent_step, new_indent);
5325 new_indent -= indent_step;
5329 o <<
string_t(new_indent,
' ') <<
"]";
5335 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
5341 o << (m_value.boolean ?
"true" :
"false");
5347 o << m_value.number_integer;
5356 o << std::setprecision(std::numeric_limits<number_float_t>::digits10) << m_value.number_float;
5383 json_value m_value = {};
5400 class primitive_iterator_t
5416 bool is_begin()
const
5418 return (m_it == begin_value);
5424 return (m_it == end_value);
5444 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5454 struct internal_iterator
5457 typename object_t::iterator object_iterator;
5459 typename array_t::iterator array_iterator;
5461 primitive_iterator_t primitive_iterator;
5465 : object_iterator(), array_iterator(), primitive_iterator()
5470 template<
typename IteratorType>
5471 class iteration_proxy
5475 class iteration_proxy_internal
5479 IteratorType anchor;
5481 size_t array_index = 0;
5484 iteration_proxy_internal(IteratorType it)
5489 iteration_proxy_internal& operator*()
5495 iteration_proxy_internal& operator++()
5504 bool operator!= (
const iteration_proxy_internal& o)
const
5506 return anchor != o.anchor;
5512 switch (anchor.m_object->type())
5517 return std::to_string(array_index);
5523 return anchor.key();
5535 typename IteratorType::reference
value()
const
5537 return anchor.value();
5542 typename IteratorType::reference container;
5546 iteration_proxy(
typename IteratorType::reference cont)
5551 iteration_proxy_internal
begin()
5553 return iteration_proxy_internal(container.begin());
5557 iteration_proxy_internal
end()
5559 return iteration_proxy_internal(container.end());
5577 class const_iterator :
public std::iterator<std::random_access_iterator_tag, const basic_json>
5580 friend class basic_json;
5600 switch (m_object->m_type)
5604 m_it.object_iterator =
typename object_t::iterator();
5610 m_it.array_iterator =
typename array_t::iterator();
5616 m_it.primitive_iterator = primitive_iterator_t();
5625 switch (m_object->m_type)
5629 m_it.object_iterator = other.m_it.object_iterator;
5635 m_it.array_iterator = other.m_it.array_iterator;
5641 m_it.primitive_iterator = other.m_it.primitive_iterator;
5649 : m_object(other.m_object), m_it(other.m_it)
5654 std::is_nothrow_move_constructible<pointer>::value and
5655 std::is_nothrow_move_assignable<pointer>::value and
5656 std::is_nothrow_move_constructible<internal_iterator>::value and
5657 std::is_nothrow_move_assignable<internal_iterator>::value
5660 std::swap(m_object, other.m_object);
5661 std::swap(m_it, other.m_it);
5669 switch (m_object->m_type)
5673 m_it.object_iterator = m_object->m_value.object->begin();
5679 m_it.array_iterator = m_object->m_value.array->begin();
5686 m_it.primitive_iterator.set_end();
5692 m_it.primitive_iterator.set_begin();
5701 switch (m_object->m_type)
5705 m_it.object_iterator = m_object->m_value.object->end();
5711 m_it.array_iterator = m_object->m_value.array->end();
5717 m_it.primitive_iterator.set_end();
5727 switch (m_object->m_type)
5731 return m_it.object_iterator->second;
5736 return *m_it.array_iterator;
5741 throw std::out_of_range(
"cannot get value");
5746 if (m_it.primitive_iterator.is_begin())
5752 throw std::out_of_range(
"cannot get value");
5761 switch (m_object->m_type)
5765 return &(m_it.object_iterator->second);
5770 return &*m_it.array_iterator;
5775 if (m_it.primitive_iterator.is_begin())
5781 throw std::out_of_range(
"cannot get value");
5790 auto result = *
this;
5798 switch (m_object->m_type)
5802 ++m_it.object_iterator;
5808 ++m_it.array_iterator;
5814 ++m_it.primitive_iterator;
5825 auto result = *
this;
5833 switch (m_object->m_type)
5837 --m_it.object_iterator;
5843 --m_it.array_iterator;
5849 --m_it.primitive_iterator;
5861 if (m_object != other.m_object)
5863 throw std::domain_error(
"cannot compare iterators of different containers");
5866 switch (m_object->m_type)
5870 return (m_it.object_iterator == other.m_it.object_iterator);
5875 return (m_it.array_iterator == other.m_it.array_iterator);
5880 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
5895 if (m_object != other.m_object)
5897 throw std::domain_error(
"cannot compare iterators of different containers");
5900 switch (m_object->m_type)
5904 throw std::domain_error(
"cannot compare order of object iterators");
5909 return (m_it.array_iterator < other.m_it.array_iterator);
5914 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
5922 return not other.operator < (*this);
5940 switch (m_object->m_type)
5944 throw std::domain_error(
"cannot use offsets with object iterators");
5949 m_it.array_iterator += i;
5955 m_it.primitive_iterator += i;
5972 auto result = *
this;
5980 auto result = *
this;
5988 switch (m_object->m_type)
5992 throw std::domain_error(
"cannot use offsets with object iterators");
5997 return m_it.array_iterator - other.m_it.array_iterator;
6002 return m_it.primitive_iterator - other.m_it.primitive_iterator;
6010 switch (m_object->m_type)
6014 throw std::domain_error(
"cannot use operator[] for object iterators");
6019 return *(m_it.array_iterator + n);
6024 throw std::out_of_range(
"cannot get value");
6029 if (m_it.primitive_iterator == -n)
6035 throw std::out_of_range(
"cannot get value");
6042 typename object_t::key_type
key()
const
6044 if (m_object->is_object())
6046 return m_it.object_iterator->first;
6050 throw std::domain_error(
"cannot use key() for non-object iterators");
6064 internal_iterator m_it = internal_iterator();
6101 std::is_nothrow_move_constructible<pointer>::value and
6102 std::is_nothrow_move_assignable<pointer>::value and
6103 std::is_nothrow_move_constructible<internal_iterator>::value and
6104 std::is_nothrow_move_assignable<internal_iterator>::value
6170 auto result = *
this;
6178 auto result = *
this;
6218 template<
typename Base>
6219 class json_reverse_iterator :
public std::reverse_iterator<Base>
6240 return base_iterator::operator++(1);
6246 base_iterator::operator++();
6253 return base_iterator::operator--(1);
6259 base_iterator::operator--();
6266 base_iterator::operator+=(i);
6273 auto result = *
this;
6281 auto result = *
this;
6289 return this->base() - other.base();
6299 typename object_t::key_type
key()
const
6301 auto it = --this->base();
6308 auto it = --this->base();
6309 return it.operator * ();
6330 enum class token_type
6349 using lexer_char_t =
unsigned char;
6352 explicit lexer(
const string_t& s) noexcept
6353 : m_stream(
nullptr), m_buffer(s)
6355 m_content =
reinterpret_cast<const lexer_char_t*
>(s.c_str());
6356 m_start = m_cursor = m_content;
6357 m_limit = m_content + s.size();
6361 explicit lexer(std::istream* s) noexcept
6362 : m_stream(s), m_buffer()
6364 getline(*m_stream, m_buffer);
6365 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
6366 m_start = m_cursor = m_content;
6367 m_limit = m_content + m_buffer.size();
6374 lexer(
const lexer&) =
delete;
6392 static string_t to_unicode(
const std::size_t codepoint1,
6393 const std::size_t codepoint2 = 0)
6398 std::size_t codepoint = codepoint1;
6401 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6404 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6418 throw std::invalid_argument(
"missing or wrong low surrogate");
6422 if (codepoint < 0x80)
6425 result.append(1, static_cast<typename string_t::value_type>(codepoint));
6427 else if (codepoint <= 0x7ff)
6430 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
6431 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6433 else if (codepoint <= 0xffff)
6436 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
6437 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6438 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6440 else if (codepoint <= 0x10ffff)
6443 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
6444 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
6445 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6446 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6450 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
6457 static std::string token_type_name(token_type t)
6461 case token_type::uninitialized:
6462 return "<uninitialized>";
6463 case token_type::literal_true:
6464 return "true literal";
6465 case token_type::literal_false:
6466 return "false literal";
6467 case token_type::literal_null:
6468 return "null literal";
6469 case token_type::value_string:
6470 return "string literal";
6471 case token_type::value_number:
6472 return "number literal";
6473 case token_type::begin_array:
6475 case token_type::begin_object:
6477 case token_type::end_array:
6479 case token_type::end_object:
6481 case token_type::name_separator:
6483 case token_type::value_separator:
6485 case token_type::parse_error:
6486 return "<parse error>";
6487 case token_type::end_of_input:
6488 return "end of input";
6492 return "unknown token";
6507 token_type scan() noexcept
6518 unsigned int yyaccept = 0;
6519 static const unsigned char yybm[] =
6521 0, 0, 0, 0, 0, 0, 0, 0,
6522 0, 32, 32, 0, 0, 32, 0, 0,
6523 64, 64, 64, 64, 64, 64, 64, 64,
6524 64, 64, 64, 64, 64, 64, 64, 64,
6525 96, 64, 0, 64, 64, 64, 64, 64,
6526 64, 64, 64, 64, 64, 64, 64, 64,
6527 192, 192, 192, 192, 192, 192, 192, 192,
6528 192, 192, 64, 64, 64, 64, 64, 64,
6529 64, 64, 64, 64, 64, 64, 64, 64,
6530 64, 64, 64, 64, 64, 64, 64, 64,
6531 64, 64, 64, 64, 64, 64, 64, 64,
6532 64, 64, 64, 64, 0, 64, 64, 64,
6533 64, 64, 64, 64, 64, 64, 64, 64,
6534 64, 64, 64, 64, 64, 64, 64, 64,
6535 64, 64, 64, 64, 64, 64, 64, 64,
6536 64, 64, 64, 64, 64, 64, 64, 64,
6537 64, 64, 64, 64, 64, 64, 64, 64,
6538 64, 64, 64, 64, 64, 64, 64, 64,
6539 64, 64, 64, 64, 64, 64, 64, 64,
6540 64, 64, 64, 64, 64, 64, 64, 64,
6541 64, 64, 64, 64, 64, 64, 64, 64,
6542 64, 64, 64, 64, 64, 64, 64, 64,
6543 64, 64, 64, 64, 64, 64, 64, 64,
6544 64, 64, 64, 64, 64, 64, 64, 64,
6545 64, 64, 64, 64, 64, 64, 64, 64,
6546 64, 64, 64, 64, 64, 64, 64, 64,
6547 64, 64, 64, 64, 64, 64, 64, 64,
6548 64, 64, 64, 64, 64, 64, 64, 64,
6549 64, 64, 64, 64, 64, 64, 64, 64,
6550 64, 64, 64, 64, 64, 64, 64, 64,
6551 64, 64, 64, 64, 64, 64, 64, 64,
6552 64, 64, 64, 64, 64, 64, 64, 64,
6554 if ((m_limit - m_cursor) < 5)
6567 goto basic_json_parser_28;
6571 goto basic_json_parser_30;
6575 goto basic_json_parser_4;
6582 goto basic_json_parser_2;
6586 goto basic_json_parser_30;
6596 goto basic_json_parser_27;
6600 goto basic_json_parser_30;
6602 goto basic_json_parser_16;
6610 goto basic_json_parser_23;
6612 goto basic_json_parser_30;
6618 goto basic_json_parser_24;
6622 goto basic_json_parser_26;
6624 goto basic_json_parser_18;
6637 goto basic_json_parser_8;
6641 goto basic_json_parser_30;
6643 goto basic_json_parser_10;
6649 goto basic_json_parser_22;
6653 goto basic_json_parser_30;
6655 goto basic_json_parser_20;
6664 goto basic_json_parser_21;
6668 goto basic_json_parser_30;
6670 goto basic_json_parser_12;
6678 goto basic_json_parser_30;
6680 goto basic_json_parser_14;
6686 goto basic_json_parser_6;
6688 goto basic_json_parser_30;
6693 basic_json_parser_2:
6696 goto basic_json_parser_5;
6697 basic_json_parser_3:
6701 basic_json_parser_4:
6703 if (m_limit <= m_cursor)
6708 basic_json_parser_5:
6709 if (yybm[0 + yych] & 32)
6711 goto basic_json_parser_4;
6713 goto basic_json_parser_3;
6714 basic_json_parser_6:
6716 yych = *(m_marker = ++m_cursor);
6719 goto basic_json_parser_64;
6721 basic_json_parser_7:
6723 return token_type::parse_error;
6725 basic_json_parser_8:
6728 return token_type::begin_array;
6730 basic_json_parser_10:
6733 return token_type::end_array;
6735 basic_json_parser_12:
6738 return token_type::begin_object;
6740 basic_json_parser_14:
6743 return token_type::end_object;
6745 basic_json_parser_16:
6748 return token_type::value_separator;
6750 basic_json_parser_18:
6753 return token_type::name_separator;
6755 basic_json_parser_20:
6757 yych = *(m_marker = ++m_cursor);
6760 goto basic_json_parser_60;
6762 goto basic_json_parser_7;
6763 basic_json_parser_21:
6765 yych = *(m_marker = ++m_cursor);
6768 goto basic_json_parser_56;
6770 goto basic_json_parser_7;
6771 basic_json_parser_22:
6773 yych = *(m_marker = ++m_cursor);
6776 goto basic_json_parser_51;
6778 goto basic_json_parser_7;
6779 basic_json_parser_23:
6783 goto basic_json_parser_7;
6787 goto basic_json_parser_50;
6791 goto basic_json_parser_41;
6793 goto basic_json_parser_7;
6794 basic_json_parser_24:
6796 yych = *(m_marker = ++m_cursor);
6801 goto basic_json_parser_43;
6808 goto basic_json_parser_44;
6812 goto basic_json_parser_44;
6815 basic_json_parser_25:
6817 return token_type::value_number;
6819 basic_json_parser_26:
6821 yych = *(m_marker = ++m_cursor);
6822 goto basic_json_parser_42;
6823 basic_json_parser_27:
6825 yych = *(m_marker = ++m_cursor);
6828 goto basic_json_parser_7;
6830 goto basic_json_parser_32;
6831 basic_json_parser_28:
6834 return token_type::end_of_input;
6836 basic_json_parser_30:
6838 goto basic_json_parser_7;
6839 basic_json_parser_31:
6841 if (m_limit <= m_cursor)
6846 basic_json_parser_32:
6847 if (yybm[0 + yych] & 64)
6849 goto basic_json_parser_31;
6853 goto basic_json_parser_33;
6857 goto basic_json_parser_35;
6859 goto basic_json_parser_34;
6860 basic_json_parser_33:
6861 m_cursor = m_marker;
6864 goto basic_json_parser_7;
6868 goto basic_json_parser_25;
6870 basic_json_parser_34:
6872 if (m_limit <= m_cursor)
6883 goto basic_json_parser_31;
6887 goto basic_json_parser_33;
6889 goto basic_json_parser_31;
6897 goto basic_json_parser_33;
6899 goto basic_json_parser_31;
6905 goto basic_json_parser_31;
6907 goto basic_json_parser_33;
6917 goto basic_json_parser_31;
6921 goto basic_json_parser_31;
6923 goto basic_json_parser_33;
6931 goto basic_json_parser_31;
6933 goto basic_json_parser_33;
6939 goto basic_json_parser_31;
6943 goto basic_json_parser_37;
6945 goto basic_json_parser_33;
6949 basic_json_parser_35:
6952 return token_type::value_string;
6954 basic_json_parser_37:
6956 if (m_limit <= m_cursor)
6965 goto basic_json_parser_33;
6969 goto basic_json_parser_33;
6976 goto basic_json_parser_38;
6980 goto basic_json_parser_33;
6984 goto basic_json_parser_33;
6987 basic_json_parser_38:
6989 if (m_limit <= m_cursor)
6998 goto basic_json_parser_33;
7002 goto basic_json_parser_33;
7009 goto basic_json_parser_39;
7013 goto basic_json_parser_33;
7017 goto basic_json_parser_33;
7020 basic_json_parser_39:
7022 if (m_limit <= m_cursor)
7031 goto basic_json_parser_33;
7035 goto basic_json_parser_33;
7042 goto basic_json_parser_40;
7046 goto basic_json_parser_33;
7050 goto basic_json_parser_33;
7053 basic_json_parser_40:
7055 if (m_limit <= m_cursor)
7064 goto basic_json_parser_33;
7068 goto basic_json_parser_31;
7070 goto basic_json_parser_33;
7076 goto basic_json_parser_31;
7080 goto basic_json_parser_33;
7084 goto basic_json_parser_31;
7086 goto basic_json_parser_33;
7088 basic_json_parser_41:
7090 m_marker = ++m_cursor;
7091 if ((m_limit - m_cursor) < 3)
7096 basic_json_parser_42:
7097 if (yybm[0 + yych] & 128)
7099 goto basic_json_parser_41;
7105 goto basic_json_parser_25;
7112 goto basic_json_parser_44;
7116 goto basic_json_parser_44;
7118 goto basic_json_parser_25;
7120 basic_json_parser_43:
7124 goto basic_json_parser_33;
7128 goto basic_json_parser_48;
7130 goto basic_json_parser_33;
7131 basic_json_parser_44:
7137 goto basic_json_parser_33;
7144 goto basic_json_parser_45;
7148 goto basic_json_parser_33;
7152 goto basic_json_parser_46;
7154 goto basic_json_parser_33;
7156 basic_json_parser_45:
7160 goto basic_json_parser_33;
7164 goto basic_json_parser_33;
7166 basic_json_parser_46:
7168 if (m_limit <= m_cursor)
7175 goto basic_json_parser_25;
7179 goto basic_json_parser_46;
7181 goto basic_json_parser_25;
7182 basic_json_parser_48:
7184 m_marker = ++m_cursor;
7185 if ((m_limit - m_cursor) < 3)
7194 goto basic_json_parser_25;
7198 goto basic_json_parser_48;
7200 goto basic_json_parser_25;
7206 goto basic_json_parser_44;
7210 goto basic_json_parser_44;
7212 goto basic_json_parser_25;
7214 basic_json_parser_50:
7216 yych = *(m_marker = ++m_cursor);
7221 goto basic_json_parser_43;
7223 goto basic_json_parser_25;
7229 goto basic_json_parser_44;
7233 goto basic_json_parser_44;
7235 goto basic_json_parser_25;
7237 basic_json_parser_51:
7241 goto basic_json_parser_33;
7246 goto basic_json_parser_33;
7251 goto basic_json_parser_33;
7255 return token_type::literal_false;
7257 basic_json_parser_56:
7261 goto basic_json_parser_33;
7266 goto basic_json_parser_33;
7270 return token_type::literal_true;
7272 basic_json_parser_60:
7276 goto basic_json_parser_33;
7281 goto basic_json_parser_33;
7285 return token_type::literal_null;
7287 basic_json_parser_64:
7291 goto basic_json_parser_33;
7303 void yyfill() noexcept
7305 if (not m_stream or not * m_stream)
7310 const ssize_t offset_start = m_start - m_content;
7311 const ssize_t offset_marker = m_marker - m_start;
7312 const ssize_t offset_cursor = m_cursor - m_start;
7314 m_buffer.erase(0, static_cast<size_t>(offset_start));
7316 std::getline(*m_stream, line);
7317 m_buffer +=
"\n" + line;
7319 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
7320 m_start = m_content;
7321 m_marker = m_start + offset_marker;
7322 m_cursor = m_start + offset_cursor;
7323 m_limit = m_start + m_buffer.size() - 1;
7327 string_t get_token() const noexcept
7329 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7330 static_cast<size_t>(m_cursor - m_start));
7357 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7360 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7416 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7417 4).c_str(),
nullptr, 16);
7420 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7423 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
7425 throw std::invalid_argument(
"missing low surrogate");
7429 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7430 (i + 7), 4).c_str(),
nullptr, 16);
7431 result += to_unicode(codepoint, codepoint2);
7438 result += to_unicode(codepoint);
7450 result.append(1, static_cast<typename string_t::value_type>(*i));
7474 long double get_number()
const
7477 typename string_t::value_type* endptr;
7478 const auto float_val = std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start),
7483 return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
7488 std::istream* m_stream;
7492 const lexer_char_t* m_content =
nullptr;
7494 const lexer_char_t* m_start =
nullptr;
7496 const lexer_char_t* m_marker =
nullptr;
7498 const lexer_char_t* m_cursor =
nullptr;
7500 const lexer_char_t* m_limit =
nullptr;
7513 : callback(cb), m_lexer(s)
7521 : callback(cb), m_lexer(&_is)
7530 basic_json result = parse_internal(
true);
7532 expect(lexer::token_type::end_of_input);
7536 return result.is_discarded() ?
basic_json() : result;
7541 basic_json parse_internal(
bool keep)
7547 case lexer::token_type::begin_object:
7560 if (last_token == lexer::token_type::end_object)
7571 unexpect(lexer::token_type::value_separator);
7577 if (last_token == lexer::token_type::value_separator)
7583 expect(lexer::token_type::value_string);
7584 const auto key = m_lexer.get_string();
7586 bool keep_tag =
false;
7602 expect(lexer::token_type::name_separator);
7606 auto value = parse_internal(keep);
7607 if (keep and keep_tag and not
value.is_discarded())
7609 result[key] = std::move(
value);
7612 while (last_token == lexer::token_type::value_separator);
7615 expect(lexer::token_type::end_object);
7625 case lexer::token_type::begin_array:
7638 if (last_token == lexer::token_type::end_array)
7649 unexpect(lexer::token_type::value_separator);
7655 if (last_token == lexer::token_type::value_separator)
7661 auto value = parse_internal(keep);
7662 if (keep and not
value.is_discarded())
7664 result.push_back(std::move(
value));
7667 while (last_token == lexer::token_type::value_separator);
7670 expect(lexer::token_type::end_array);
7680 case lexer::token_type::literal_null:
7687 case lexer::token_type::value_string:
7689 const auto s = m_lexer.get_string();
7695 case lexer::token_type::literal_true:
7699 result.m_value =
true;
7703 case lexer::token_type::literal_false:
7707 result.m_value =
false;
7711 case lexer::token_type::value_number:
7713 auto float_val = m_lexer.get_number();
7717 if (std::isnan(float_val))
7719 throw std::invalid_argument(std::string(
"parse error - ") +
7720 m_lexer.get_token() +
" is not a number");
7727 if (approx(float_val, static_cast<long double>(int_val)))
7731 result.m_value = int_val;
7745 unexpect(last_token);
7757 typename lexer::token_type get_token()
7759 last_token = m_lexer.scan();
7763 void expect(
typename lexer::token_type t)
const
7765 if (t != last_token)
7767 std::string error_msg =
"parse error - unexpected ";
7768 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token() +
"'") :
7769 lexer::token_type_name(last_token));
7770 error_msg +=
"; expected " + lexer::token_type_name(t);
7771 throw std::invalid_argument(error_msg);
7775 void unexpect(
typename lexer::token_type t)
const
7777 if (t == last_token)
7779 std::string error_msg =
"parse error - unexpected ";
7780 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token() +
"'") :
7781 lexer::token_type_name(last_token));
7782 throw std::invalid_argument(error_msg);
7792 typename lexer::token_type last_token = lexer::token_type::uninitialized;
7830 is_nothrow_move_constructible<nlohmann::json>::value and
7831 is_nothrow_move_assignable<nlohmann::json>::value
7849 const auto& h = hash<nlohmann::json::string_t>();
7867 inline nlohmann::json operator "" _json(
const char* s, std::size_t)
7870 (const_cast<char*>(s)));
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json 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)
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
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
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
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
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
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