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();
3924 return m_value.array->size();
3929 return m_value.object->size();
3978 return m_value.array->max_size();
3983 return m_value.object->max_size();
4035 m_value.number_integer = 0;
4041 m_value.number_float = 0.0;
4047 m_value.boolean =
false;
4053 m_value.string->clear();
4059 m_value.array->clear();
4065 m_value.object->clear();
4101 throw std::domain_error(
"cannot use push_back() with " + type_name());
4112 m_value.array->push_back(std::move(val));
4136 throw std::domain_error(
"cannot use push_back() with " + type_name());
4147 m_value.array->push_back(val);
4185 throw std::domain_error(
"cannot use push_back() with " + type_name());
4196 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());
4290 if (pos.m_object !=
this)
4292 throw std::domain_error(
"iterator does not fit current value");
4297 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4302 throw std::domain_error(
"cannot use insert() with " + type_name());
4340 throw std::domain_error(
"cannot use insert() with " + type_name());
4344 if (pos.m_object !=
this)
4346 throw std::domain_error(
"iterator does not fit current value");
4349 if (first.m_object != last.m_object)
4351 throw std::domain_error(
"iterators do not fit");
4354 if (first.m_object ==
this or last.m_object ==
this)
4356 throw std::domain_error(
"passed iterators may not belong to container");
4361 result.m_it.array_iterator = m_value.array->insert(
4362 pos.m_it.array_iterator,
4363 first.m_it.array_iterator,
4364 last.m_it.array_iterator);
4395 throw std::domain_error(
"cannot use insert() with " + type_name());
4399 if (pos.m_object !=
this)
4401 throw std::domain_error(
"iterator does not fit current value");
4406 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4428 std::is_nothrow_move_constructible<value_t>::value and
4429 std::is_nothrow_move_assignable<value_t>::value and
4430 std::is_nothrow_move_constructible<json_value>::value and
4431 std::is_nothrow_move_assignable<json_value>::value
4434 std::swap(m_type, other.m_type);
4435 std::swap(m_value, other.m_value);
4462 std::swap(*(m_value.array), other);
4466 throw std::domain_error(
"cannot use swap() with " + type_name());
4494 std::swap(*(m_value.object), other);
4498 throw std::domain_error(
"cannot use swap() with " + type_name());
4526 std::swap(*(m_value.string), other);
4530 throw std::domain_error(
"cannot use swap() with " + type_name());
4556 static constexpr std::array<uint8_t, 7> order = {{
4573 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
4602 const auto lhs_type = lhs.type();
4603 const auto rhs_type = rhs.type();
4605 if (lhs_type == rhs_type)
4610 return *lhs.m_value.array == *rhs.m_value.array;
4612 return *lhs.m_value.object == *rhs.m_value.object;
4616 return *lhs.m_value.string == *rhs.m_value.string;
4618 return lhs.m_value.boolean == rhs.m_value.boolean;
4620 return lhs.m_value.number_integer == rhs.m_value.number_integer;
4622 return approx(lhs.m_value.number_float, rhs.m_value.number_float);
4629 return approx(static_cast<number_float_t>(lhs.m_value.number_integer),
4630 rhs.m_value.number_float);
4634 return approx(lhs.m_value.number_float,
4635 static_cast<number_float_t>(rhs.m_value.number_integer));
4690 return not (lhs == rhs);
4722 return not v.is_null();
4751 const auto lhs_type = lhs.type();
4752 const auto rhs_type = rhs.type();
4754 if (lhs_type == rhs_type)
4759 return *lhs.m_value.array < *rhs.m_value.array;
4761 return *lhs.m_value.object < *rhs.m_value.object;
4765 return *lhs.m_value.string < *rhs.m_value.string;
4767 return lhs.m_value.boolean < rhs.m_value.boolean;
4769 return lhs.m_value.number_integer < rhs.m_value.number_integer;
4771 return lhs.m_value.number_float < rhs.m_value.number_float;
4779 rhs.m_value.number_float;
4783 return lhs.m_value.number_float <
4812 return not (rhs < lhs);
4834 return not (lhs <= rhs);
4856 return not (lhs < rhs);
4891 friend std::ostream&
operator<<(std::ostream& o,
const basic_json& j)
4894 const bool pretty_print = (o.width() > 0);
4895 const auto indentation = (pretty_print ? o.width() : 0);
4901 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
4909 friend std::ostream&
operator>>(
const basic_json& j, std::ostream& o)
4950 return parser(s, cb).
parse();
4979 return parser(i, cb).
parse();
4987 return parser(i, cb).
parse();
5015 j = parser(i).
parse();
5025 j = parser(i).
parse();
5067 static std::size_t extra_space(
const string_t& s) noexcept
5069 std::size_t result = 0;
5071 for (
const auto& c : s)
5090 if (c >= 0x00 and c <= 0x1f)
5118 const auto space = extra_space(s);
5125 string_t result(s.size() + space,
'\\');
5126 std::size_t pos = 0;
5128 for (
const auto& c : s)
5135 result[pos + 1] =
'"';
5151 result[pos + 1] =
'b';
5159 result[pos + 1] =
'f';
5167 result[pos + 1] =
'n';
5175 result[pos + 1] =
'r';
5183 result[pos + 1] =
't';
5190 if (c >= 0x00 and c <= 0x1f)
5193 auto hexify = [](
const char v) ->
char
5195 return (v < 10) ? (
'0' + v) : (
'a' + v - 10);
5200 {
'u',
'0',
'0', hexify(c >> 4), hexify(c & 0x0f)
5238 void dump(std::ostream& o,
5239 const bool pretty_print,
5240 const unsigned int indent_step,
5241 const unsigned int current_indent = 0)
const
5244 unsigned int new_indent = current_indent;
5250 if (m_value.object->empty())
5261 new_indent += indent_step;
5265 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5267 if (i != m_value.object->cbegin())
5269 o << (pretty_print ?
",\n" :
",");
5271 o <<
string_t(new_indent,
' ') <<
"\""
5272 << escape_string(i->first) <<
"\":"
5273 << (pretty_print ?
" " :
"");
5274 i->second.dump(o, pretty_print, indent_step, new_indent);
5280 new_indent -= indent_step;
5284 o <<
string_t(new_indent,
' ') +
"}";
5290 if (m_value.array->empty())
5301 new_indent += indent_step;
5305 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5307 if (i != m_value.array->cbegin())
5309 o << (pretty_print ?
",\n" :
",");
5312 i->dump(o, pretty_print, indent_step, new_indent);
5318 new_indent -= indent_step;
5322 o <<
string_t(new_indent,
' ') <<
"]";
5328 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
5334 o << (m_value.boolean ?
"true" :
"false");
5340 o << m_value.number_integer;
5349 o << std::setprecision(std::numeric_limits<number_float_t>::digits10) << m_value.number_float;
5376 json_value m_value = {};
5393 class primitive_iterator_t
5409 bool is_begin()
const
5411 return (m_it == begin_value);
5417 return (m_it == end_value);
5437 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5447 struct internal_iterator
5450 typename object_t::iterator object_iterator;
5452 typename array_t::iterator array_iterator;
5454 primitive_iterator_t primitive_iterator;
5458 : object_iterator(), array_iterator(), primitive_iterator()
5463 template<
typename IteratorType>
5464 class iteration_proxy
5468 class iteration_proxy_internal
5472 IteratorType anchor;
5474 size_t array_index = 0;
5477 iteration_proxy_internal(IteratorType it)
5482 iteration_proxy_internal& operator*()
5488 iteration_proxy_internal& operator++()
5497 bool operator!= (
const iteration_proxy_internal& o)
5499 return anchor != o.anchor;
5505 switch (anchor.m_object->type())
5510 return std::to_string(array_index);
5516 return anchor.key();
5528 typename IteratorType::reference
value()
const
5530 return anchor.value();
5535 typename IteratorType::reference container;
5539 iteration_proxy(
typename IteratorType::reference cont)
5544 iteration_proxy_internal
begin()
5546 return iteration_proxy_internal(container.begin());
5550 iteration_proxy_internal
end()
5552 return iteration_proxy_internal(container.end());
5570 class const_iterator :
public std::iterator<std::random_access_iterator_tag, const basic_json>
5573 friend class basic_json;
5593 switch (m_object->m_type)
5597 m_it.object_iterator =
typename object_t::iterator();
5603 m_it.array_iterator =
typename array_t::iterator();
5609 m_it.primitive_iterator = primitive_iterator_t();
5618 switch (m_object->m_type)
5622 m_it.object_iterator = other.m_it.object_iterator;
5628 m_it.array_iterator = other.m_it.array_iterator;
5634 m_it.primitive_iterator = other.m_it.primitive_iterator;
5642 : m_object(other.m_object), m_it(other.m_it)
5647 std::is_nothrow_move_constructible<pointer>::value and
5648 std::is_nothrow_move_assignable<pointer>::value and
5649 std::is_nothrow_move_constructible<internal_iterator>::value and
5650 std::is_nothrow_move_assignable<internal_iterator>::value
5653 std::swap(m_object, other.m_object);
5654 std::swap(m_it, other.m_it);
5662 switch (m_object->m_type)
5666 m_it.object_iterator = m_object->m_value.object->begin();
5672 m_it.array_iterator = m_object->m_value.array->begin();
5679 m_it.primitive_iterator.set_end();
5685 m_it.primitive_iterator.set_begin();
5694 switch (m_object->m_type)
5698 m_it.object_iterator = m_object->m_value.object->end();
5704 m_it.array_iterator = m_object->m_value.array->end();
5710 m_it.primitive_iterator.set_end();
5720 switch (m_object->m_type)
5724 return m_it.object_iterator->second;
5729 return *m_it.array_iterator;
5734 throw std::out_of_range(
"cannot get value");
5739 if (m_it.primitive_iterator.is_begin())
5745 throw std::out_of_range(
"cannot get value");
5754 switch (m_object->m_type)
5758 return &(m_it.object_iterator->second);
5763 return &*m_it.array_iterator;
5768 if (m_it.primitive_iterator.is_begin())
5774 throw std::out_of_range(
"cannot get value");
5783 auto result = *
this;
5791 switch (m_object->m_type)
5795 ++m_it.object_iterator;
5801 ++m_it.array_iterator;
5807 ++m_it.primitive_iterator;
5818 auto result = *
this;
5826 switch (m_object->m_type)
5830 --m_it.object_iterator;
5836 --m_it.array_iterator;
5842 --m_it.primitive_iterator;
5854 if (m_object != other.m_object)
5856 throw std::domain_error(
"cannot compare iterators of different containers");
5859 switch (m_object->m_type)
5863 return (m_it.object_iterator == other.m_it.object_iterator);
5868 return (m_it.array_iterator == other.m_it.array_iterator);
5873 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
5888 if (m_object != other.m_object)
5890 throw std::domain_error(
"cannot compare iterators of different containers");
5893 switch (m_object->m_type)
5897 throw std::domain_error(
"cannot compare order of object iterators");
5902 return (m_it.array_iterator < other.m_it.array_iterator);
5907 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
5915 return not other.operator < (*this);
5933 switch (m_object->m_type)
5937 throw std::domain_error(
"cannot use offsets with object iterators");
5942 m_it.array_iterator += i;
5948 m_it.primitive_iterator += i;
5965 auto result = *
this;
5973 auto result = *
this;
5981 switch (m_object->m_type)
5985 throw std::domain_error(
"cannot use offsets with object iterators");
5990 return m_it.array_iterator - other.m_it.array_iterator;
5995 return m_it.primitive_iterator - other.m_it.primitive_iterator;
6003 switch (m_object->m_type)
6007 throw std::domain_error(
"cannot use operator[] for object iterators");
6012 return *(m_it.array_iterator + n);
6017 throw std::out_of_range(
"cannot get value");
6022 if (m_it.primitive_iterator == -n)
6028 throw std::out_of_range(
"cannot get value");
6035 typename object_t::key_type
key()
const
6037 if (m_object->is_object())
6039 return m_it.object_iterator->first;
6043 throw std::domain_error(
"cannot use key() for non-object iterators");
6057 internal_iterator m_it = internal_iterator();
6094 std::is_nothrow_move_constructible<pointer>::value and
6095 std::is_nothrow_move_assignable<pointer>::value and
6096 std::is_nothrow_move_constructible<internal_iterator>::value and
6097 std::is_nothrow_move_assignable<internal_iterator>::value
6163 auto result = *
this;
6171 auto result = *
this;
6211 template<
typename Base>
6212 class json_reverse_iterator :
public std::reverse_iterator<Base>
6233 return base_iterator::operator++(1);
6239 base_iterator::operator++();
6246 return base_iterator::operator--(1);
6252 base_iterator::operator--();
6259 base_iterator::operator+=(i);
6266 auto result = *
this;
6274 auto result = *
this;
6282 return this->base() - other.base();
6292 typename object_t::key_type
key()
const
6294 auto it = --this->base();
6301 auto it = --this->base();
6302 return it.operator * ();
6323 enum class token_type
6342 using lexer_char_t =
unsigned char;
6345 explicit lexer(
const string_t& s) noexcept
6346 : m_stream(
nullptr), m_buffer(s)
6348 m_content =
reinterpret_cast<const lexer_char_t*
>(s.c_str());
6349 m_start = m_cursor = m_content;
6350 m_limit = m_content + s.size();
6352 explicit lexer(std::istream* s) noexcept
6353 : m_stream(s), m_buffer()
6355 getline(*m_stream, m_buffer);
6356 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
6357 m_start = m_cursor = m_content;
6358 m_limit = m_content + m_buffer.size();
6365 lexer(
const lexer&) =
delete;
6380 static string_t to_unicode(
const std::size_t codepoint1,
6381 const std::size_t codepoint2 = 0)
6386 std::size_t codepoint = codepoint1;
6389 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6392 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6406 throw std::invalid_argument(
"missing or wrong low surrogate");
6410 if (codepoint < 0x80)
6413 result.append(1, static_cast<typename string_t::value_type>(codepoint));
6415 else if (codepoint <= 0x7ff)
6418 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
6419 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6421 else if (codepoint <= 0xffff)
6424 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
6425 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6426 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6428 else if (codepoint <= 0x10ffff)
6431 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
6432 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
6433 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6434 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6438 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
6445 static std::string token_type_name(token_type t)
6449 case token_type::uninitialized:
6450 return "<uninitialized>";
6451 case token_type::literal_true:
6452 return "true literal";
6453 case token_type::literal_false:
6454 return "false literal";
6455 case token_type::literal_null:
6456 return "null literal";
6457 case token_type::value_string:
6458 return "string literal";
6459 case token_type::value_number:
6460 return "number literal";
6461 case token_type::begin_array:
6463 case token_type::begin_object:
6465 case token_type::end_array:
6467 case token_type::end_object:
6469 case token_type::name_separator:
6471 case token_type::value_separator:
6473 case token_type::parse_error:
6474 return "<parse error>";
6475 case token_type::end_of_input:
6476 return "end of input";
6480 return "unknown token";
6495 token_type scan() noexcept
6506 unsigned int yyaccept = 0;
6507 static const unsigned char yybm[] =
6509 0, 0, 0, 0, 0, 0, 0, 0,
6510 0, 32, 32, 0, 0, 32, 0, 0,
6511 64, 64, 64, 64, 64, 64, 64, 64,
6512 64, 64, 64, 64, 64, 64, 64, 64,
6513 96, 64, 0, 64, 64, 64, 64, 64,
6514 64, 64, 64, 64, 64, 64, 64, 64,
6515 192, 192, 192, 192, 192, 192, 192, 192,
6516 192, 192, 64, 64, 64, 64, 64, 64,
6517 64, 64, 64, 64, 64, 64, 64, 64,
6518 64, 64, 64, 64, 64, 64, 64, 64,
6519 64, 64, 64, 64, 64, 64, 64, 64,
6520 64, 64, 64, 64, 0, 64, 64, 64,
6521 64, 64, 64, 64, 64, 64, 64, 64,
6522 64, 64, 64, 64, 64, 64, 64, 64,
6523 64, 64, 64, 64, 64, 64, 64, 64,
6524 64, 64, 64, 64, 64, 64, 64, 64,
6525 64, 64, 64, 64, 64, 64, 64, 64,
6526 64, 64, 64, 64, 64, 64, 64, 64,
6527 64, 64, 64, 64, 64, 64, 64, 64,
6528 64, 64, 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, 64, 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,
6542 if ((m_limit - m_cursor) < 5)
6555 goto basic_json_parser_28;
6559 goto basic_json_parser_30;
6563 goto basic_json_parser_4;
6570 goto basic_json_parser_2;
6574 goto basic_json_parser_30;
6584 goto basic_json_parser_27;
6588 goto basic_json_parser_30;
6590 goto basic_json_parser_16;
6598 goto basic_json_parser_23;
6600 goto basic_json_parser_30;
6606 goto basic_json_parser_24;
6610 goto basic_json_parser_26;
6612 goto basic_json_parser_18;
6625 goto basic_json_parser_8;
6629 goto basic_json_parser_30;
6631 goto basic_json_parser_10;
6637 goto basic_json_parser_22;
6641 goto basic_json_parser_30;
6643 goto basic_json_parser_20;
6652 goto basic_json_parser_21;
6656 goto basic_json_parser_30;
6658 goto basic_json_parser_12;
6666 goto basic_json_parser_30;
6668 goto basic_json_parser_14;
6674 goto basic_json_parser_6;
6676 goto basic_json_parser_30;
6681 basic_json_parser_2:
6684 goto basic_json_parser_5;
6685 basic_json_parser_3:
6689 basic_json_parser_4:
6691 if (m_limit <= m_cursor)
6696 basic_json_parser_5:
6697 if (yybm[0 + yych] & 32)
6699 goto basic_json_parser_4;
6701 goto basic_json_parser_3;
6702 basic_json_parser_6:
6704 yych = *(m_marker = ++m_cursor);
6707 goto basic_json_parser_64;
6709 basic_json_parser_7:
6711 return token_type::parse_error;
6713 basic_json_parser_8:
6716 return token_type::begin_array;
6718 basic_json_parser_10:
6721 return token_type::end_array;
6723 basic_json_parser_12:
6726 return token_type::begin_object;
6728 basic_json_parser_14:
6731 return token_type::end_object;
6733 basic_json_parser_16:
6736 return token_type::value_separator;
6738 basic_json_parser_18:
6741 return token_type::name_separator;
6743 basic_json_parser_20:
6745 yych = *(m_marker = ++m_cursor);
6748 goto basic_json_parser_60;
6750 goto basic_json_parser_7;
6751 basic_json_parser_21:
6753 yych = *(m_marker = ++m_cursor);
6756 goto basic_json_parser_56;
6758 goto basic_json_parser_7;
6759 basic_json_parser_22:
6761 yych = *(m_marker = ++m_cursor);
6764 goto basic_json_parser_51;
6766 goto basic_json_parser_7;
6767 basic_json_parser_23:
6771 goto basic_json_parser_7;
6775 goto basic_json_parser_50;
6779 goto basic_json_parser_41;
6781 goto basic_json_parser_7;
6782 basic_json_parser_24:
6784 yych = *(m_marker = ++m_cursor);
6789 goto basic_json_parser_43;
6796 goto basic_json_parser_44;
6800 goto basic_json_parser_44;
6803 basic_json_parser_25:
6805 return token_type::value_number;
6807 basic_json_parser_26:
6809 yych = *(m_marker = ++m_cursor);
6810 goto basic_json_parser_42;
6811 basic_json_parser_27:
6813 yych = *(m_marker = ++m_cursor);
6816 goto basic_json_parser_7;
6818 goto basic_json_parser_32;
6819 basic_json_parser_28:
6822 return token_type::end_of_input;
6824 basic_json_parser_30:
6826 goto basic_json_parser_7;
6827 basic_json_parser_31:
6829 if (m_limit <= m_cursor)
6834 basic_json_parser_32:
6835 if (yybm[0 + yych] & 64)
6837 goto basic_json_parser_31;
6841 goto basic_json_parser_33;
6845 goto basic_json_parser_35;
6847 goto basic_json_parser_34;
6848 basic_json_parser_33:
6849 m_cursor = m_marker;
6852 goto basic_json_parser_7;
6856 goto basic_json_parser_25;
6858 basic_json_parser_34:
6860 if (m_limit <= m_cursor)
6871 goto basic_json_parser_31;
6875 goto basic_json_parser_33;
6877 goto basic_json_parser_31;
6885 goto basic_json_parser_33;
6887 goto basic_json_parser_31;
6893 goto basic_json_parser_31;
6895 goto basic_json_parser_33;
6905 goto basic_json_parser_31;
6909 goto basic_json_parser_31;
6911 goto basic_json_parser_33;
6919 goto basic_json_parser_31;
6921 goto basic_json_parser_33;
6927 goto basic_json_parser_31;
6931 goto basic_json_parser_37;
6933 goto basic_json_parser_33;
6937 basic_json_parser_35:
6940 return token_type::value_string;
6942 basic_json_parser_37:
6944 if (m_limit <= m_cursor)
6953 goto basic_json_parser_33;
6957 goto basic_json_parser_33;
6964 goto basic_json_parser_38;
6968 goto basic_json_parser_33;
6972 goto basic_json_parser_33;
6975 basic_json_parser_38:
6977 if (m_limit <= m_cursor)
6986 goto basic_json_parser_33;
6990 goto basic_json_parser_33;
6997 goto basic_json_parser_39;
7001 goto basic_json_parser_33;
7005 goto basic_json_parser_33;
7008 basic_json_parser_39:
7010 if (m_limit <= m_cursor)
7019 goto basic_json_parser_33;
7023 goto basic_json_parser_33;
7030 goto basic_json_parser_40;
7034 goto basic_json_parser_33;
7038 goto basic_json_parser_33;
7041 basic_json_parser_40:
7043 if (m_limit <= m_cursor)
7052 goto basic_json_parser_33;
7056 goto basic_json_parser_31;
7058 goto basic_json_parser_33;
7064 goto basic_json_parser_31;
7068 goto basic_json_parser_33;
7072 goto basic_json_parser_31;
7074 goto basic_json_parser_33;
7076 basic_json_parser_41:
7078 m_marker = ++m_cursor;
7079 if ((m_limit - m_cursor) < 3)
7084 basic_json_parser_42:
7085 if (yybm[0 + yych] & 128)
7087 goto basic_json_parser_41;
7093 goto basic_json_parser_25;
7100 goto basic_json_parser_44;
7104 goto basic_json_parser_44;
7106 goto basic_json_parser_25;
7108 basic_json_parser_43:
7112 goto basic_json_parser_33;
7116 goto basic_json_parser_48;
7118 goto basic_json_parser_33;
7119 basic_json_parser_44:
7125 goto basic_json_parser_33;
7132 goto basic_json_parser_45;
7136 goto basic_json_parser_33;
7140 goto basic_json_parser_46;
7142 goto basic_json_parser_33;
7144 basic_json_parser_45:
7148 goto basic_json_parser_33;
7152 goto basic_json_parser_33;
7154 basic_json_parser_46:
7156 if (m_limit <= m_cursor)
7163 goto basic_json_parser_25;
7167 goto basic_json_parser_46;
7169 goto basic_json_parser_25;
7170 basic_json_parser_48:
7172 m_marker = ++m_cursor;
7173 if ((m_limit - m_cursor) < 3)
7182 goto basic_json_parser_25;
7186 goto basic_json_parser_48;
7188 goto basic_json_parser_25;
7194 goto basic_json_parser_44;
7198 goto basic_json_parser_44;
7200 goto basic_json_parser_25;
7202 basic_json_parser_50:
7204 yych = *(m_marker = ++m_cursor);
7209 goto basic_json_parser_43;
7211 goto basic_json_parser_25;
7217 goto basic_json_parser_44;
7221 goto basic_json_parser_44;
7223 goto basic_json_parser_25;
7225 basic_json_parser_51:
7229 goto basic_json_parser_33;
7234 goto basic_json_parser_33;
7239 goto basic_json_parser_33;
7243 return token_type::literal_false;
7245 basic_json_parser_56:
7249 goto basic_json_parser_33;
7254 goto basic_json_parser_33;
7258 return token_type::literal_true;
7260 basic_json_parser_60:
7264 goto basic_json_parser_33;
7269 goto basic_json_parser_33;
7273 return token_type::literal_null;
7275 basic_json_parser_64:
7279 goto basic_json_parser_33;
7291 void yyfill() noexcept
7293 if (not m_stream or not * m_stream)
7298 const ssize_t offset_start = m_start - m_content;
7299 const ssize_t offset_marker = m_marker - m_start;
7300 const ssize_t offset_cursor = m_cursor - m_start;
7302 m_buffer.erase(0, static_cast<size_t>(offset_start));
7304 std::getline(*m_stream, line);
7305 m_buffer +=
"\n" + line;
7307 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
7308 m_start = m_content;
7309 m_marker = m_start + offset_marker;
7310 m_cursor = m_start + offset_cursor;
7311 m_limit = m_start + m_buffer.size() - 1;
7315 string_t get_token() const noexcept
7317 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7318 static_cast<size_t>(m_cursor - m_start));
7345 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7348 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7404 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7405 4).c_str(),
nullptr, 16);
7408 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7411 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
7413 throw std::invalid_argument(
"missing low surrogate");
7417 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7418 (i + 7), 4).c_str(),
nullptr, 16);
7419 result += to_unicode(codepoint, codepoint2);
7426 result += to_unicode(codepoint);
7438 result.append(1, static_cast<typename string_t::value_type>(*i));
7462 long double get_number()
const
7465 typename string_t::value_type* endptr;
7466 const auto float_val = std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start),
7471 return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
7476 std::istream* m_stream;
7480 const lexer_char_t* m_content =
nullptr;
7482 const lexer_char_t* m_start =
nullptr;
7484 const lexer_char_t* m_marker =
nullptr;
7486 const lexer_char_t* m_cursor =
nullptr;
7488 const lexer_char_t* m_limit =
nullptr;
7501 : callback(cb), m_lexer(s)
7509 : callback(cb), m_lexer(&_is)
7518 basic_json result = parse_internal(
true);
7520 expect(lexer::token_type::end_of_input);
7524 return result.is_discarded() ?
basic_json() : result;
7529 basic_json parse_internal(
bool keep)
7535 case lexer::token_type::begin_object:
7548 if (last_token == lexer::token_type::end_object)
7559 unexpect(lexer::token_type::value_separator);
7565 if (last_token == lexer::token_type::value_separator)
7571 expect(lexer::token_type::value_string);
7572 const auto key = m_lexer.get_string();
7574 bool keep_tag =
false;
7590 expect(lexer::token_type::name_separator);
7594 auto value = parse_internal(keep);
7595 if (keep and keep_tag and not
value.is_discarded())
7597 result[key] = std::move(
value);
7600 while (last_token == lexer::token_type::value_separator);
7603 expect(lexer::token_type::end_object);
7613 case lexer::token_type::begin_array:
7626 if (last_token == lexer::token_type::end_array)
7637 unexpect(lexer::token_type::value_separator);
7643 if (last_token == lexer::token_type::value_separator)
7649 auto value = parse_internal(keep);
7650 if (keep and not
value.is_discarded())
7652 result.push_back(std::move(
value));
7655 while (last_token == lexer::token_type::value_separator);
7658 expect(lexer::token_type::end_array);
7668 case lexer::token_type::literal_null:
7675 case lexer::token_type::value_string:
7677 const auto s = m_lexer.get_string();
7683 case lexer::token_type::literal_true:
7687 result.m_value =
true;
7691 case lexer::token_type::literal_false:
7695 result.m_value =
false;
7699 case lexer::token_type::value_number:
7701 auto float_val = m_lexer.get_number();
7705 if (std::isnan(float_val))
7707 throw std::invalid_argument(std::string(
"parse error - ") +
7708 m_lexer.get_token() +
" is not a number");
7715 if (approx(float_val, static_cast<long double>(int_val)))
7719 result.m_value = int_val;
7733 unexpect(last_token);
7745 typename lexer::token_type get_token()
7747 last_token = m_lexer.scan();
7751 void expect(
typename lexer::token_type t)
const
7753 if (t != last_token)
7755 std::string error_msg =
"parse error - unexpected ";
7756 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token() +
"'") :
7757 lexer::token_type_name(last_token));
7758 error_msg +=
"; expected " + lexer::token_type_name(t);
7759 throw std::invalid_argument(error_msg);
7763 void unexpect(
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 throw std::invalid_argument(error_msg);
7780 typename lexer::token_type last_token = lexer::token_type::uninitialized;
7818 is_nothrow_move_constructible<nlohmann::json>::value and
7819 is_nothrow_move_assignable<nlohmann::json>::value
7837 const auto& h = hash<nlohmann::json::string_t>();
7855 inline nlohmann::json operator "" _json(
const char* s, std::size_t)
7858 (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