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;
91 struct has_mapped_type
94 template<
typename C>
static char test(
typename C::mapped_type*);
95 template<
typename C>
static int test(...);
97 enum { value =
sizeof(test<T>(0)) ==
sizeof(char) };
102 static bool approx(
const T a,
const T b)
104 return not (a > b or a < b);
173 template<
typename U,
typename V,
typename... Args>
class ObjectType = std::map,
174 template<
typename U,
typename... Args>
class ArrayType = std::vector,
175 class StringType = std::string,
176 class BooleanType = bool,
177 class NumberIntegerType = int64_t,
178 class NumberFloatType = double,
179 template<
typename U>
class AllocatorType = std::allocator
221 using pointer =
typename std::allocator_traits<allocator_type>::pointer;
223 using const_pointer =
typename std::allocator_traits<allocator_type>::const_pointer;
324 using object_t = ObjectType<StringType,
326 std::less<StringType>,
327 AllocatorType<std::pair<
const StringType,
371 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
610 template<
typename T,
typename... Args>
611 static T* create(Args&& ... args)
613 AllocatorType<T> alloc;
614 auto deleter = [&](T *
object)
616 alloc.deallocate(
object, 1);
618 std::unique_ptr<T, decltype(deleter)>
object(alloc.allocate(1), deleter);
619 alloc.construct(
object.
get(), std::forward<Args>(args)...);
620 return object.release();
650 json_value() noexcept = default;
652 json_value(
boolean_t v) noexcept :
boolean(v) {}
664 object = create<object_t>();
670 array = create<array_t>();
676 string = create<string_t>(
"");
708 string = create<string_t>(
value);
714 object = create<object_t>(
value);
720 array = create<array_t>(
value);
803 using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
844 : m_type(value), m_value(value)
887 basic_json(
std::nullptr_t) noexcept
911 : m_type(
value_t::object), m_value(value)
937 template <
class CompatibleObjectType,
typename
939 std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
940 std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value,
int>
::type
947 m_value.object = create<object_t>(
begin(value),
end(value));
970 : m_type(
value_t::array), m_value(value)
996 template <
class CompatibleArrayType,
typename
998 not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
999 not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1000 not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1001 not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1002 not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1003 not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1004 std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value,
int>::type
1011 m_value.array = create<array_t>(
begin(value),
end(value));
1036 : m_type(
value_t::string), m_value(value)
1086 template <
class CompatibleStringType,
typename
1088 std::is_constructible<string_t, CompatibleStringType>::value,
int>::type
1109 : m_type(
value_t::boolean), m_value(value)
1137 template<
typename T,
1138 typename std::enable_if<
1139 not (std::is_same<T, int>::value)
1143 : m_type(
value_t::number_integer), m_value(value)
1172 : m_type(
value_t::number_integer),
1201 template<
typename CompatibleNumberIntegerType,
typename
1203 std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1204 std::numeric_limits<CompatibleNumberIntegerType>::is_integer, CompatibleNumberIntegerType>::type
1208 m_value(static_cast<number_integer_t>(
value))
1236 : m_type(
value_t::number_float), m_value(value)
1239 if (not std::isfinite(value))
1242 m_value = json_value();
1276 template<
typename CompatibleNumberFloatType,
typename =
typename
1278 std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1279 std::is_floating_point<CompatibleNumberFloatType>::value>::type
1354 bool type_deduction =
true,
1362 for (
const auto& element : init)
1364 if (not element.is_array() or element.size() != 2
1365 or not element[0].is_string())
1375 if (not type_deduction)
1386 throw std::domain_error(
"cannot create object from initializer list");
1396 for (
auto& element : init)
1398 m_value.object->emplace(std::move(*(element[0].m_value.string)), std::move(element[1]));
1405 m_value.array = create<array_t>(std::move(init));
1443 static basic_json
array(std::initializer_list<basic_json> init =
1444 std::initializer_list<basic_json>())
1483 static basic_json
object(std::initializer_list<basic_json> init =
1484 std::initializer_list<basic_json>())
1510 m_value.array = create<array_t>(
count,
value);
1545 template <
class InputIT,
typename
1547 std::is_same<InputIT, typename basic_json_t::iterator>::value or
1548 std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1551 basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1554 if (first.m_object != last.m_object)
1556 throw std::domain_error(
"iterators are not compatible");
1567 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1569 throw std::out_of_range(
"iterators out of range");
1584 m_value.number_integer = first.m_object->m_value.number_integer;
1590 m_value.number_float = first.m_object->m_value.number_float;
1596 m_value.boolean = first.m_object->m_value.boolean;
1602 m_value = *first.m_object->m_value.string;
1608 m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1614 m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1620 throw std::domain_error(
"cannot use construct with iterators from " + first.m_object->type_name());
1650 : m_type(other.m_type)
1656 m_value = *other.m_value.object;
1662 m_value = *other.m_value.array;
1668 m_value = *other.m_value.string;
1674 m_value = other.m_value.boolean;
1680 m_value = other.m_value.number_integer;
1686 m_value = other.m_value.number_float;
1716 : m_type(
std::move(other.m_type)),
1717 m_value(
std::move(other.m_value))
1744 std::is_nothrow_move_constructible<value_t>::value and
1745 std::is_nothrow_move_assignable<value_t>::value and
1746 std::is_nothrow_move_constructible<json_value>::value and
1747 std::is_nothrow_move_assignable<json_value>::value
1751 swap(m_type, other.m_type);
1752 swap(m_value, other.m_value);
1775 AllocatorType<object_t> alloc;
1776 alloc.destroy(m_value.object);
1777 alloc.deallocate(m_value.object, 1);
1783 AllocatorType<array_t> alloc;
1784 alloc.destroy(m_value.array);
1785 alloc.deallocate(m_value.array, 1);
1791 AllocatorType<string_t> alloc;
1792 alloc.destroy(m_value.string);
1793 alloc.deallocate(m_value.string, 1);
1837 std::stringstream ss;
1841 dump(ss,
true, static_cast<unsigned int>(indent));
2093 template <
class T,
typename
2095 std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2096 std::is_convertible<basic_json_t, typename T::mapped_type>::value
2098 T get_impl(T*)
const
2102 return T(m_value.object->begin(), m_value.object->end());
2106 throw std::domain_error(
"type must be object, but is " + type_name());
2115 return *(m_value.object);
2119 throw std::domain_error(
"type must be object, but is " + type_name());
2124 template <
class T,
typename
2126 std::is_convertible<basic_json_t, typename T::value_type>::value and
2127 not std::is_same<basic_json_t, typename T::value_type>::value and
2128 not std::is_arithmetic<T>::value and
2129 not std::is_convertible<std::string, T>::value and
2130 not has_mapped_type<T>::value
2132 T get_impl(T*)
const
2137 std::transform(m_value.array->begin(), m_value.array->end(),
2138 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2140 return i.get<
typename T::value_type>();
2146 throw std::domain_error(
"type must be array, but is " + type_name());
2151 template <
class T,
typename
2153 std::is_convertible<basic_json_t, T>::value and
2154 not std::is_same<basic_json_t, T>::value
2156 std::vector<T> get_impl(std::vector<T>*)
const
2160 std::vector<T> to_vector;
2161 to_vector.reserve(m_value.array->size());
2162 std::transform(m_value.array->begin(), m_value.array->end(),
2163 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2171 throw std::domain_error(
"type must be array, but is " + type_name());
2176 template <
class T,
typename
2178 std::is_same<basic_json, typename T::value_type>::value and
2179 not has_mapped_type<T>::value
2181 T get_impl(T*)
const
2185 return T(m_value.array->begin(), m_value.array->end());
2189 throw std::domain_error(
"type must be array, but is " + type_name());
2198 return *(m_value.array);
2202 throw std::domain_error(
"type must be array, but is " + type_name());
2207 template <
typename T,
typename
2209 std::is_convertible<string_t, T>::value
2211 T get_impl(T*)
const
2215 return *m_value.string;
2219 throw std::domain_error(
"type must be string, but is " + type_name());
2224 template<
typename T,
typename
2226 std::is_arithmetic<T>::value
2228 T get_impl(T*)
const
2234 return static_cast<T
>(m_value.number_integer);
2239 return static_cast<T
>(m_value.number_float);
2244 throw std::domain_error(
"type must be number, but is " + type_name());
2254 return m_value.boolean;
2258 throw std::domain_error(
"type must be boolean, but is " + type_name());
2265 return is_object() ? m_value.object :
nullptr;
2271 return is_object() ? m_value.object :
nullptr;
2277 return is_array() ? m_value.array :
nullptr;
2283 return is_array() ? m_value.array :
nullptr;
2289 return is_string() ? m_value.string :
nullptr;
2295 return is_string() ? m_value.string :
nullptr;
2301 return is_boolean() ? &m_value.boolean :
nullptr;
2307 return is_boolean() ? &m_value.boolean :
nullptr;
2370 template<
typename ValueType,
typename
2372 not std::is_pointer<ValueType>::value
2374 ValueType
get()
const
2376 return get_impl(static_cast<ValueType*>(
nullptr));
2404 template<
typename PointerType,
typename
2406 std::is_pointer<PointerType>::value
2408 PointerType
get() noexcept
2411 return get_ptr<PointerType>();
2418 template<
typename PointerType,
typename
2420 std::is_pointer<PointerType>::value
2422 const PointerType
get()
const noexcept
2425 return get_ptr<PointerType>();
2451 template<
typename PointerType,
typename
2453 std::is_pointer<PointerType>::value
2458 return get_impl_ptr(static_cast<PointerType>(
nullptr));
2465 template<
typename PointerType,
typename
2467 std::is_pointer<PointerType>::value
2468 and std::is_const<typename std::remove_pointer<PointerType>::type>
::value
2473 return get_impl_ptr(static_cast<const PointerType>(
nullptr));
2500 template<
typename ValueType,
typename
2502 not std::is_pointer<ValueType>::value
2504 operator ValueType()
const
2507 return get<ValueType>();
2544 return m_value.array->at(idx);
2548 throw std::domain_error(
"cannot use at() with " + type_name());
2576 return m_value.array->at(idx);
2580 throw std::domain_error(
"cannot use at() with " + type_name());
2612 return m_value.object->at(key);
2616 throw std::domain_error(
"cannot use at() with " + type_name());
2648 return m_value.object->at(key);
2652 throw std::domain_error(
"cannot use at() with " + type_name());
2684 m_value.array = create<array_t>();
2690 for (
size_t i = m_value.array->size(); i <= idx; ++i)
2695 return m_value.array->operator[](idx);
2699 throw std::domain_error(
"cannot use operator[] with " + type_name());
2724 return m_value.array->operator[](idx);
2728 throw std::domain_error(
"cannot use operator[] with " + type_name());
2762 m_value.object = create<object_t>();
2768 return m_value.object->operator[](key);
2772 throw std::domain_error(
"cannot use operator[] with " + type_name());
2802 template<
typename T, std::
size_t n>
2815 return m_value.object->operator[](key);
2819 throw std::domain_error(
"cannot use operator[] with " + type_name());
2868 template <
class ValueType,
typename
2870 std::is_convertible<basic_json_t, ValueType>::value
2872 ValueType
value(
const typename object_t::key_type& key, ValueType default_value)
const
2878 const auto it =
find(key);
2885 return default_value;
2890 throw std::domain_error(
"cannot use value() with " + type_name());
2898 string_t value(
const typename object_t::key_type& key,
const char* default_value)
const
3003 template <
class InteratorType,
typename
3005 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3006 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3012 if (
this != pos.m_object)
3014 throw std::domain_error(
"iterator does not fit current value");
3017 InteratorType result =
end();
3026 if (not pos.m_it.primitive_iterator.is_begin())
3028 throw std::out_of_range(
"iterator out of range");
3033 delete m_value.string;
3034 m_value.string =
nullptr;
3043 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3049 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3055 throw std::domain_error(
"cannot use erase() with " + type_name());
3096 template <
class InteratorType,
typename
3098 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3099 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3102 InteratorType
erase(InteratorType first, InteratorType last)
3105 if (
this != first.m_object or
this != last.m_object)
3107 throw std::domain_error(
"iterators do not fit current value");
3110 InteratorType result =
end();
3119 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3121 throw std::out_of_range(
"iterators out of range");
3126 delete m_value.string;
3127 m_value.string =
nullptr;
3136 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3137 last.m_it.object_iterator);
3143 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3144 last.m_it.array_iterator);
3150 throw std::domain_error(
"cannot use erase with " + type_name());
3179 return m_value.object->erase(key);
3183 throw std::domain_error(
"cannot use erase() with " + type_name());
3208 throw std::out_of_range(
"index out of range");
3211 m_value.array->erase(m_value.array->begin() +
static_cast<difference_type>(idx));
3215 throw std::domain_error(
"cannot use erase() with " + type_name());
3236 auto result =
end();
3240 result.m_it.object_iterator = m_value.object->find(key);
3252 auto result =
cend();
3256 result.m_it.object_iterator = m_value.object->find(key);
3281 return (
is_object()) ? m_value.object->count(key) : 0;
3551 return m_value.array->empty();
3556 return m_value.object->empty();
3605 return m_value.array->size();
3610 return m_value.object->size();
3657 return m_value.array->max_size();
3662 return m_value.object->max_size();
3712 m_value.number_integer = 0;
3718 m_value.number_float = 0.0;
3724 m_value.boolean =
false;
3730 m_value.string->clear();
3736 m_value.array->clear();
3742 m_value.object->clear();
3775 throw std::domain_error(
"cannot use push_back() with " + type_name());
3786 m_value.array->push_back(std::move(
value));
3810 throw std::domain_error(
"cannot use push_back() with " + type_name());
3821 m_value.array->push_back(value);
3857 throw std::domain_error(
"cannot use push_back() with " + type_name());
3868 m_value.object->insert(value);
3905 if (pos.m_object !=
this)
3907 throw std::domain_error(
"iterator does not fit current value");
3912 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, value);
3917 throw std::domain_error(
"cannot use insert() with " + type_name());
3956 if (pos.m_object !=
this)
3958 throw std::domain_error(
"iterator does not fit current value");
3963 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, count, value);
3968 throw std::domain_error(
"cannot use insert() with " + type_name());
4001 throw std::domain_error(
"cannot use insert() with " + type_name());
4005 if (pos.m_object !=
this)
4007 throw std::domain_error(
"iterator does not fit current value");
4010 if (first.m_object != last.m_object)
4012 throw std::domain_error(
"iterators does not fit");
4015 if (first.m_object ==
this or last.m_object ==
this)
4017 throw std::domain_error(
"passed iterators may not belong to container");
4022 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator,
4023 first.m_it.array_iterator, last.m_it.array_iterator);
4051 throw std::domain_error(
"cannot use insert() with " + type_name());
4055 if (pos.m_object !=
this)
4057 throw std::domain_error(
"iterator does not fit current value");
4062 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4082 std::is_nothrow_move_constructible<value_t>::value and
4083 std::is_nothrow_move_assignable<value_t>::value and
4084 std::is_nothrow_move_constructible<json_value>::value and
4085 std::is_nothrow_move_assignable<json_value>::value
4088 std::swap(m_type, other.m_type);
4089 std::swap(m_value, other.m_value);
4114 std::swap(*(m_value.array), other);
4118 throw std::domain_error(
"cannot use swap() with " + type_name());
4144 std::swap(*(m_value.object), other);
4148 throw std::domain_error(
"cannot use swap() with " + type_name());
4174 std::swap(*(m_value.string), other);
4178 throw std::domain_error(
"cannot use swap() with " + type_name());
4202 static constexpr std::array<uint8_t, 7> order = {{
4219 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
4246 const auto lhs_type = lhs.type();
4247 const auto rhs_type = rhs.type();
4249 if (lhs_type == rhs_type)
4254 return *lhs.m_value.array == *rhs.m_value.array;
4256 return *lhs.m_value.object == *rhs.m_value.object;
4260 return *lhs.m_value.string == *rhs.m_value.string;
4262 return lhs.m_value.boolean == rhs.m_value.boolean;
4264 return lhs.m_value.number_integer == rhs.m_value.number_integer;
4266 return approx(lhs.m_value.number_float, rhs.m_value.number_float);
4273 return approx(static_cast<number_float_t>(lhs.m_value.number_integer),
4274 rhs.m_value.number_float);
4278 return approx(lhs.m_value.number_float,
4279 static_cast<number_float_t>(rhs.m_value.number_integer));
4330 return not (lhs == rhs);
4360 return not v.is_null();
4387 const auto lhs_type = lhs.type();
4388 const auto rhs_type = rhs.type();
4390 if (lhs_type == rhs_type)
4395 return *lhs.m_value.array < *rhs.m_value.array;
4397 return *lhs.m_value.object < *rhs.m_value.object;
4401 return *lhs.m_value.string < *rhs.m_value.string;
4403 return lhs.m_value.boolean < rhs.m_value.boolean;
4405 return lhs.m_value.number_integer < rhs.m_value.number_integer;
4407 return lhs.m_value.number_float < rhs.m_value.number_float;
4415 rhs.m_value.number_float;
4419 return lhs.m_value.number_float <
4446 return not (rhs < lhs);
4466 return not (lhs <= rhs);
4486 return not (lhs < rhs);
4519 friend std::ostream&
operator<<(std::ostream& o,
const basic_json& j)
4522 const bool pretty_print = (o.width() > 0);
4523 const auto indentation = (pretty_print ? o.width() : 0);
4529 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
4537 friend std::ostream&
operator>>(
const basic_json& j, std::ostream& o)
4576 return parser(s, cb).
parse();
4603 return parser(i, cb).
parse();
4608 return parser(i, cb).
parse();
4634 j = parser(i).
parse();
4644 j = parser(i).
parse();
4706 static std::size_t extra_space(
const string_t& s) noexcept
4708 std::size_t result = 0;
4710 for (
const auto& c : s)
4729 if (c >= 0x00 and c <= 0x1f)
4757 const auto space = extra_space(s);
4764 string_t result(s.size() + space,
'\\');
4765 std::size_t pos = 0;
4767 for (
const auto& c : s)
4774 result[pos + 1] =
'"';
4790 result[pos + 1] =
'b';
4798 result[pos + 1] =
'f';
4806 result[pos + 1] =
'n';
4814 result[pos + 1] =
'r';
4822 result[pos + 1] =
't';
4829 if (c >= 0x00 and c <= 0x1f)
4832 auto hexify = [](
const char v) ->
char
4834 return (v < 10) ? (
'0' + v) : (
'a' + v - 10);
4839 {
'u',
'0',
'0', hexify(c >> 4), hexify(c & 0x0f)
4877 void dump(std::ostream& o,
const bool pretty_print,
const unsigned int indent_step,
4878 const unsigned int current_indent = 0)
const
4881 unsigned int new_indent = current_indent;
4887 if (m_value.object->empty())
4898 new_indent += indent_step;
4902 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
4904 if (i != m_value.object->cbegin())
4906 o << (pretty_print ?
",\n" :
",");
4908 o <<
string_t(new_indent,
' ') <<
"\""
4909 << escape_string(i->first) <<
"\":"
4910 << (pretty_print ?
" " :
"");
4911 i->second.dump(o, pretty_print, indent_step, new_indent);
4917 new_indent -= indent_step;
4921 o <<
string_t(new_indent,
' ') +
"}";
4927 if (m_value.array->empty())
4938 new_indent += indent_step;
4942 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
4944 if (i != m_value.array->cbegin())
4946 o << (pretty_print ?
",\n" :
",");
4949 i->dump(o, pretty_print, indent_step, new_indent);
4955 new_indent -= indent_step;
4959 o <<
string_t(new_indent,
' ') <<
"]";
4965 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
4971 o << (m_value.boolean ?
"true" :
"false");
4977 o << m_value.number_integer;
4986 o << std::setprecision(std::numeric_limits<number_float_t>::digits10) << m_value.number_float;
5013 json_value m_value = {};
5030 class primitive_iterator_t
5046 bool is_begin()
const
5048 return (m_it == begin_value);
5054 return (m_it == end_value);
5074 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5084 struct internal_iterator
5087 typename object_t::iterator object_iterator;
5089 typename array_t::iterator array_iterator;
5091 primitive_iterator_t primitive_iterator;
5095 : object_iterator(), array_iterator(), primitive_iterator()
5111 class const_iterator :
public std::iterator<std::random_access_iterator_tag, const basic_json>
5114 friend class basic_json;
5134 switch (m_object->m_type)
5138 m_it.object_iterator =
typename object_t::iterator();
5144 m_it.array_iterator =
typename array_t::iterator();
5150 m_it.primitive_iterator = primitive_iterator_t();
5159 switch (m_object->m_type)
5163 m_it.object_iterator = other.m_it.object_iterator;
5169 m_it.array_iterator = other.m_it.array_iterator;
5175 m_it.primitive_iterator = other.m_it.primitive_iterator;
5183 : m_object(other.m_object), m_it(other.m_it)
5188 std::is_nothrow_move_constructible<pointer>::value and
5189 std::is_nothrow_move_assignable<pointer>::value and
5190 std::is_nothrow_move_constructible<internal_iterator>::value and
5191 std::is_nothrow_move_assignable<internal_iterator>::value
5194 std::swap(m_object, other.m_object);
5195 std::swap(m_it, other.m_it);
5203 switch (m_object->m_type)
5207 m_it.object_iterator = m_object->m_value.object->begin();
5213 m_it.array_iterator = m_object->m_value.array->begin();
5220 m_it.primitive_iterator.set_end();
5226 m_it.primitive_iterator.set_begin();
5235 switch (m_object->m_type)
5239 m_it.object_iterator = m_object->m_value.object->end();
5245 m_it.array_iterator = m_object->m_value.array->end();
5251 m_it.primitive_iterator.set_end();
5261 switch (m_object->m_type)
5265 return m_it.object_iterator->second;
5270 return *m_it.array_iterator;
5275 throw std::out_of_range(
"cannot get value");
5280 if (m_it.primitive_iterator.is_begin())
5286 throw std::out_of_range(
"cannot get value");
5295 switch (m_object->m_type)
5299 return &(m_it.object_iterator->second);
5304 return &*m_it.array_iterator;
5309 if (m_it.primitive_iterator.is_begin())
5315 throw std::out_of_range(
"cannot get value");
5324 auto result = *
this;
5333 switch (m_object->m_type)
5337 ++m_it.object_iterator;
5343 ++m_it.array_iterator;
5349 ++m_it.primitive_iterator;
5360 auto result = *
this;
5369 switch (m_object->m_type)
5373 --m_it.object_iterator;
5379 --m_it.array_iterator;
5385 --m_it.primitive_iterator;
5397 if (m_object != other.m_object)
5399 throw std::domain_error(
"cannot compare iterators of different containers");
5402 switch (m_object->m_type)
5406 return (m_it.object_iterator == other.m_it.object_iterator);
5411 return (m_it.array_iterator == other.m_it.array_iterator);
5416 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
5431 if (m_object != other.m_object)
5433 throw std::domain_error(
"cannot compare iterators of different containers");
5436 switch (m_object->m_type)
5440 throw std::domain_error(
"cannot use operator< for object iterators");
5445 return (m_it.array_iterator < other.m_it.array_iterator);
5450 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
5458 return not other.operator < (*this);
5476 switch (m_object->m_type)
5480 throw std::domain_error(
"cannot use operator+= for object iterators");
5485 m_it.array_iterator += i;
5491 m_it.primitive_iterator += i;
5508 auto result = *
this;
5516 auto result = *
this;
5524 switch (m_object->m_type)
5528 throw std::domain_error(
"cannot use operator- for object iterators");
5533 return m_it.array_iterator - other.m_it.array_iterator;
5538 return m_it.primitive_iterator - other.m_it.primitive_iterator;
5546 switch (m_object->m_type)
5550 throw std::domain_error(
"cannot use operator[] for object iterators");
5555 return *(m_it.array_iterator + n);
5560 throw std::out_of_range(
"cannot get value");
5565 if (m_it.primitive_iterator == -n)
5571 throw std::out_of_range(
"cannot get value");
5578 typename object_t::key_type
key()
const
5580 if (m_object->is_object())
5582 return m_it.object_iterator->first;
5586 throw std::domain_error(
"cannot use key() for non-object iterators");
5600 internal_iterator m_it = internal_iterator();
5634 std::is_nothrow_move_constructible<pointer>::value and
5635 std::is_nothrow_move_assignable<pointer>::value and
5636 std::is_nothrow_move_constructible<internal_iterator>::value and
5637 std::is_nothrow_move_assignable<internal_iterator>::value
5703 auto result = *
this;
5711 auto result = *
this;
5749 template<
typename Base>
5750 class json_reverse_iterator :
public std::reverse_iterator<Base>
5768 return base_iterator::operator++(1);
5774 base_iterator::operator++();
5781 return base_iterator::operator--(1);
5787 base_iterator::operator--();
5794 base_iterator::operator+=(i);
5801 auto result = *
this;
5809 auto result = *
this;
5817 return this->base() - other.base();
5827 typename object_t::key_type
key()
const
5829 auto it = --this->base();
5836 auto it = --this->base();
5837 return it.operator * ();
5852 basic_json& container;
5854 using json_iterator = decltype(std::begin(container));
5857 class iterator_wrapper_internal
5861 json_iterator anchor;
5863 size_t array_index = 0;
5867 iterator_wrapper_internal(json_iterator i) : anchor(i)
5871 iterator_wrapper_internal& operator*()
5877 iterator_wrapper_internal& operator++()
5886 bool operator!= (
const iterator_wrapper_internal& o)
5888 return anchor != o.anchor;
5894 switch (anchor.m_object->type())
5899 return std::to_string(array_index);
5905 return anchor.key();
5917 typename json_iterator::reference
value()
const
5919 return anchor.value();
5932 return iterator_wrapper_internal(container.
begin());
5936 iterator_wrapper_internal
end()
5938 return iterator_wrapper_internal(container.
end());
5958 enum class token_type
5977 using lexer_char_t =
unsigned char;
5980 explicit lexer(
const string_t& s) noexcept
5981 : m_stream(
nullptr), m_buffer(s)
5983 m_content =
reinterpret_cast<const lexer_char_t*
>(s.c_str());
5984 m_start = m_cursor = m_content;
5985 m_limit = m_content + s.size();
5987 explicit lexer(std::istream* s) noexcept
5988 : m_stream(s), m_buffer()
5990 getline(*m_stream, m_buffer);
5991 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
5992 m_start = m_cursor = m_content;
5993 m_limit = m_content + m_buffer.size();
6000 lexer(
const lexer&) =
delete;
6014 static string_t to_unicode(
const std::size_t codepoint1,
6015 const std::size_t codepoint2 = 0)
6020 std::size_t codepoint = codepoint1;
6023 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6026 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6040 throw std::invalid_argument(
"missing or wrong low surrogate");
6044 if (codepoint < 0x80)
6047 result.append(1, static_cast<typename string_t::value_type>(codepoint));
6049 else if (codepoint <= 0x7ff)
6052 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
6053 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6055 else if (codepoint <= 0xffff)
6058 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
6059 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6060 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6062 else if (codepoint <= 0x10ffff)
6065 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
6066 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
6067 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6068 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6072 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
6079 static std::string token_type_name(token_type t)
6083 case token_type::uninitialized:
6084 return "<uninitialized>";
6085 case token_type::literal_true:
6086 return "true literal";
6087 case token_type::literal_false:
6088 return "false literal";
6089 case token_type::literal_null:
6090 return "null literal";
6091 case token_type::value_string:
6092 return "string literal";
6093 case token_type::value_number:
6094 return "number literal";
6095 case token_type::begin_array:
6097 case token_type::begin_object:
6099 case token_type::end_array:
6101 case token_type::end_object:
6103 case token_type::name_separator:
6105 case token_type::value_separator:
6107 case token_type::end_of_input:
6108 return "<end of input>";
6109 case token_type::parse_error:
6110 return "<parse error>";
6124 token_type scan() noexcept
6135 unsigned int yyaccept = 0;
6136 static const unsigned char yybm[] =
6138 0, 0, 0, 0, 0, 0, 0, 0,
6139 0, 32, 32, 0, 0, 32, 0, 0,
6140 64, 64, 64, 64, 64, 64, 64, 64,
6141 64, 64, 64, 64, 64, 64, 64, 64,
6142 96, 64, 0, 64, 64, 64, 64, 64,
6143 64, 64, 64, 64, 64, 64, 64, 64,
6144 192, 192, 192, 192, 192, 192, 192, 192,
6145 192, 192, 64, 64, 64, 64, 64, 64,
6146 64, 64, 64, 64, 64, 64, 64, 64,
6147 64, 64, 64, 64, 64, 64, 64, 64,
6148 64, 64, 64, 64, 64, 64, 64, 64,
6149 64, 64, 64, 64, 0, 64, 64, 64,
6150 64, 64, 64, 64, 64, 64, 64, 64,
6151 64, 64, 64, 64, 64, 64, 64, 64,
6152 64, 64, 64, 64, 64, 64, 64, 64,
6153 64, 64, 64, 64, 64, 64, 64, 64,
6154 64, 64, 64, 64, 64, 64, 64, 64,
6155 64, 64, 64, 64, 64, 64, 64, 64,
6156 64, 64, 64, 64, 64, 64, 64, 64,
6157 64, 64, 64, 64, 64, 64, 64, 64,
6158 64, 64, 64, 64, 64, 64, 64, 64,
6159 64, 64, 64, 64, 64, 64, 64, 64,
6160 64, 64, 64, 64, 64, 64, 64, 64,
6161 64, 64, 64, 64, 64, 64, 64, 64,
6162 64, 64, 64, 64, 64, 64, 64, 64,
6163 64, 64, 64, 64, 64, 64, 64, 64,
6164 64, 64, 64, 64, 64, 64, 64, 64,
6165 64, 64, 64, 64, 64, 64, 64, 64,
6166 64, 64, 64, 64, 64, 64, 64, 64,
6167 64, 64, 64, 64, 64, 64, 64, 64,
6168 64, 64, 64, 64, 64, 64, 64, 64,
6169 64, 64, 64, 64, 64, 64, 64, 64,
6171 if ((m_limit - m_cursor) < 5)
6184 goto basic_json_parser_28;
6188 goto basic_json_parser_30;
6192 goto basic_json_parser_4;
6199 goto basic_json_parser_2;
6203 goto basic_json_parser_30;
6213 goto basic_json_parser_27;
6217 goto basic_json_parser_30;
6219 goto basic_json_parser_16;
6227 goto basic_json_parser_23;
6229 goto basic_json_parser_30;
6235 goto basic_json_parser_24;
6239 goto basic_json_parser_26;
6241 goto basic_json_parser_18;
6254 goto basic_json_parser_8;
6258 goto basic_json_parser_30;
6260 goto basic_json_parser_10;
6266 goto basic_json_parser_22;
6270 goto basic_json_parser_30;
6272 goto basic_json_parser_20;
6281 goto basic_json_parser_21;
6285 goto basic_json_parser_30;
6287 goto basic_json_parser_12;
6295 goto basic_json_parser_30;
6297 goto basic_json_parser_14;
6303 goto basic_json_parser_6;
6305 goto basic_json_parser_30;
6310 basic_json_parser_2:
6313 goto basic_json_parser_5;
6314 basic_json_parser_3:
6318 basic_json_parser_4:
6320 if (m_limit <= m_cursor)
6325 basic_json_parser_5:
6326 if (yybm[0 + yych] & 32)
6328 goto basic_json_parser_4;
6330 goto basic_json_parser_3;
6331 basic_json_parser_6:
6333 yych = *(m_marker = ++m_cursor);
6336 goto basic_json_parser_64;
6338 basic_json_parser_7:
6340 return token_type::parse_error;
6342 basic_json_parser_8:
6345 return token_type::begin_array;
6347 basic_json_parser_10:
6350 return token_type::end_array;
6352 basic_json_parser_12:
6355 return token_type::begin_object;
6357 basic_json_parser_14:
6360 return token_type::end_object;
6362 basic_json_parser_16:
6365 return token_type::value_separator;
6367 basic_json_parser_18:
6370 return token_type::name_separator;
6372 basic_json_parser_20:
6374 yych = *(m_marker = ++m_cursor);
6377 goto basic_json_parser_60;
6379 goto basic_json_parser_7;
6380 basic_json_parser_21:
6382 yych = *(m_marker = ++m_cursor);
6385 goto basic_json_parser_56;
6387 goto basic_json_parser_7;
6388 basic_json_parser_22:
6390 yych = *(m_marker = ++m_cursor);
6393 goto basic_json_parser_51;
6395 goto basic_json_parser_7;
6396 basic_json_parser_23:
6400 goto basic_json_parser_7;
6404 goto basic_json_parser_50;
6408 goto basic_json_parser_41;
6410 goto basic_json_parser_7;
6411 basic_json_parser_24:
6413 yych = *(m_marker = ++m_cursor);
6418 goto basic_json_parser_43;
6425 goto basic_json_parser_44;
6429 goto basic_json_parser_44;
6432 basic_json_parser_25:
6434 return token_type::value_number;
6436 basic_json_parser_26:
6438 yych = *(m_marker = ++m_cursor);
6439 goto basic_json_parser_42;
6440 basic_json_parser_27:
6442 yych = *(m_marker = ++m_cursor);
6445 goto basic_json_parser_7;
6447 goto basic_json_parser_32;
6448 basic_json_parser_28:
6451 return token_type::end_of_input;
6453 basic_json_parser_30:
6455 goto basic_json_parser_7;
6456 basic_json_parser_31:
6458 if (m_limit <= m_cursor)
6463 basic_json_parser_32:
6464 if (yybm[0 + yych] & 64)
6466 goto basic_json_parser_31;
6470 goto basic_json_parser_33;
6474 goto basic_json_parser_35;
6476 goto basic_json_parser_34;
6477 basic_json_parser_33:
6478 m_cursor = m_marker;
6481 goto basic_json_parser_7;
6485 goto basic_json_parser_25;
6487 basic_json_parser_34:
6489 if (m_limit <= m_cursor)
6500 goto basic_json_parser_31;
6504 goto basic_json_parser_33;
6506 goto basic_json_parser_31;
6514 goto basic_json_parser_33;
6516 goto basic_json_parser_31;
6522 goto basic_json_parser_31;
6524 goto basic_json_parser_33;
6534 goto basic_json_parser_31;
6538 goto basic_json_parser_31;
6540 goto basic_json_parser_33;
6548 goto basic_json_parser_31;
6550 goto basic_json_parser_33;
6556 goto basic_json_parser_31;
6560 goto basic_json_parser_37;
6562 goto basic_json_parser_33;
6566 basic_json_parser_35:
6569 return token_type::value_string;
6571 basic_json_parser_37:
6573 if (m_limit <= m_cursor)
6582 goto basic_json_parser_33;
6586 goto basic_json_parser_33;
6593 goto basic_json_parser_38;
6597 goto basic_json_parser_33;
6601 goto basic_json_parser_33;
6604 basic_json_parser_38:
6606 if (m_limit <= m_cursor)
6615 goto basic_json_parser_33;
6619 goto basic_json_parser_33;
6626 goto basic_json_parser_39;
6630 goto basic_json_parser_33;
6634 goto basic_json_parser_33;
6637 basic_json_parser_39:
6639 if (m_limit <= m_cursor)
6648 goto basic_json_parser_33;
6652 goto basic_json_parser_33;
6659 goto basic_json_parser_40;
6663 goto basic_json_parser_33;
6667 goto basic_json_parser_33;
6670 basic_json_parser_40:
6672 if (m_limit <= m_cursor)
6681 goto basic_json_parser_33;
6685 goto basic_json_parser_31;
6687 goto basic_json_parser_33;
6693 goto basic_json_parser_31;
6697 goto basic_json_parser_33;
6701 goto basic_json_parser_31;
6703 goto basic_json_parser_33;
6705 basic_json_parser_41:
6707 m_marker = ++m_cursor;
6708 if ((m_limit - m_cursor) < 3)
6713 basic_json_parser_42:
6714 if (yybm[0 + yych] & 128)
6716 goto basic_json_parser_41;
6722 goto basic_json_parser_25;
6729 goto basic_json_parser_44;
6733 goto basic_json_parser_44;
6735 goto basic_json_parser_25;
6737 basic_json_parser_43:
6741 goto basic_json_parser_33;
6745 goto basic_json_parser_48;
6747 goto basic_json_parser_33;
6748 basic_json_parser_44:
6754 goto basic_json_parser_33;
6761 goto basic_json_parser_45;
6765 goto basic_json_parser_33;
6769 goto basic_json_parser_46;
6771 goto basic_json_parser_33;
6773 basic_json_parser_45:
6777 goto basic_json_parser_33;
6781 goto basic_json_parser_33;
6783 basic_json_parser_46:
6785 if (m_limit <= m_cursor)
6792 goto basic_json_parser_25;
6796 goto basic_json_parser_46;
6798 goto basic_json_parser_25;
6799 basic_json_parser_48:
6801 m_marker = ++m_cursor;
6802 if ((m_limit - m_cursor) < 3)
6811 goto basic_json_parser_25;
6815 goto basic_json_parser_48;
6817 goto basic_json_parser_25;
6823 goto basic_json_parser_44;
6827 goto basic_json_parser_44;
6829 goto basic_json_parser_25;
6831 basic_json_parser_50:
6833 yych = *(m_marker = ++m_cursor);
6838 goto basic_json_parser_43;
6840 goto basic_json_parser_25;
6846 goto basic_json_parser_44;
6850 goto basic_json_parser_44;
6852 goto basic_json_parser_25;
6854 basic_json_parser_51:
6858 goto basic_json_parser_33;
6863 goto basic_json_parser_33;
6868 goto basic_json_parser_33;
6872 return token_type::literal_false;
6874 basic_json_parser_56:
6878 goto basic_json_parser_33;
6883 goto basic_json_parser_33;
6887 return token_type::literal_true;
6889 basic_json_parser_60:
6893 goto basic_json_parser_33;
6898 goto basic_json_parser_33;
6902 return token_type::literal_null;
6904 basic_json_parser_64:
6908 goto basic_json_parser_33;
6920 void yyfill() noexcept
6922 if (not m_stream or not * m_stream)
6927 const ssize_t offset_start = m_start - m_content;
6928 const ssize_t offset_marker = m_marker - m_start;
6929 const ssize_t offset_cursor = m_cursor - m_start;
6931 m_buffer.erase(0, static_cast<size_t>(offset_start));
6933 std::getline(*m_stream, line);
6934 m_buffer +=
"\n" + line;
6936 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
6937 m_start = m_content;
6938 m_marker = m_start + offset_marker;
6939 m_cursor = m_start + offset_cursor;
6940 m_limit = m_start + m_buffer.size() - 1;
6944 string_t get_token() const noexcept
6946 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
6947 static_cast<size_t>(m_cursor - m_start));
6974 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
6977 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7033 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7034 4).c_str(),
nullptr, 16);
7037 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7040 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
7042 throw std::invalid_argument(
"missing low surrogate");
7046 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7047 (i + 7), 4).c_str(),
nullptr, 16);
7048 result += to_unicode(codepoint, codepoint2);
7055 result += to_unicode(codepoint);
7067 result.append(1, static_cast<typename string_t::value_type>(*i));
7091 long double get_number()
const
7094 typename string_t::value_type* endptr;
7095 const auto float_val = std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start),
7100 return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
7105 std::istream* m_stream;
7109 const lexer_char_t* m_content =
nullptr;
7111 const lexer_char_t* m_start =
nullptr;
7113 const lexer_char_t* m_marker =
nullptr;
7115 const lexer_char_t* m_cursor =
nullptr;
7117 const lexer_char_t* m_limit =
nullptr;
7128 : callback(cb), m_lexer(s)
7136 : callback(cb), m_lexer(&_is)
7145 basic_json result = parse_internal(
true);
7147 expect(lexer::token_type::end_of_input);
7151 return result.is_discarded() ?
basic_json() : result;
7156 basic_json parse_internal(
bool keep)
7162 case lexer::token_type::begin_object:
7175 if (last_token == lexer::token_type::end_object)
7186 unexpect(lexer::token_type::value_separator);
7192 if (last_token == lexer::token_type::value_separator)
7198 expect(lexer::token_type::value_string);
7199 const auto key = m_lexer.get_string();
7201 bool keep_tag =
false;
7217 expect(lexer::token_type::name_separator);
7221 auto value = parse_internal(keep);
7222 if (keep and keep_tag and not
value.is_discarded())
7224 result[key] = std::move(
value);
7227 while (last_token == lexer::token_type::value_separator);
7230 expect(lexer::token_type::end_object);
7240 case lexer::token_type::begin_array:
7253 if (last_token == lexer::token_type::end_array)
7264 unexpect(lexer::token_type::value_separator);
7270 if (last_token == lexer::token_type::value_separator)
7276 auto value = parse_internal(keep);
7277 if (keep and not
value.is_discarded())
7279 result.push_back(std::move(
value));
7282 while (last_token == lexer::token_type::value_separator);
7285 expect(lexer::token_type::end_array);
7295 case lexer::token_type::literal_null:
7302 case lexer::token_type::value_string:
7304 const auto s = m_lexer.get_string();
7310 case lexer::token_type::literal_true:
7314 result.m_value =
true;
7318 case lexer::token_type::literal_false:
7322 result.m_value =
false;
7326 case lexer::token_type::value_number:
7328 auto float_val = m_lexer.get_number();
7332 if (std::isnan(float_val))
7334 throw std::invalid_argument(std::string(
"parse error - ") +
7335 m_lexer.get_token() +
" is not a number");
7342 if (approx(float_val, static_cast<long double>(int_val)))
7346 result.m_value = int_val;
7360 unexpect(last_token);
7372 typename lexer::token_type get_token()
7374 last_token = m_lexer.scan();
7378 void expect(
typename lexer::token_type t)
const
7380 if (t != last_token)
7382 std::string error_msg =
"parse error - unexpected \'";
7383 error_msg += m_lexer.get_token();
7384 error_msg +=
"\' (" + lexer::token_type_name(last_token);
7385 error_msg +=
"); expected " + lexer::token_type_name(t);
7386 throw std::invalid_argument(error_msg);
7390 void unexpect(
typename lexer::token_type t)
const
7392 if (t == last_token)
7394 std::string error_msg =
"parse error - unexpected \'";
7395 error_msg += m_lexer.get_token();
7396 error_msg +=
"\' (";
7397 error_msg += lexer::token_type_name(last_token) +
")";
7398 throw std::invalid_argument(error_msg);
7408 typename lexer::token_type last_token = lexer::token_type::uninitialized;
7442 is_nothrow_move_constructible<nlohmann::json>::value and
7443 is_nothrow_move_assignable<nlohmann::json>::value
7457 const auto& h = hash<nlohmann::json::string_t>();
7473 inline nlohmann::json operator "" _json(
const char* s, std::size_t)
7476 (const_cast<char*>(s)));
basic_json(const number_float_t value)
create a floating-point number (explicit)
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
iterator_wrapper(basic_json &cont)
construct iterator wrapper from a container
bool operator!=(const const_iterator &other) const
comparison: not equal
iterator operator++(int)
post-increment (it++)
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
iterator insert(const_iterator pos, basic_json &&value)
inserts element
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
static basic_json object(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an object from an initializer list
const_reference operator[](size_type idx) const
access specified array element
reference operator[](const T(&key)[n])
access specified object element
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
const_iterator & operator--()
pre-decrement (–it)
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
const_iterator & operator=(const_iterator other) noexcept( std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value )
copy assignment
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
reference & operator=(basic_json other) noexcept( std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value )
copy assignment
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
basic_json(const int value)
create an integer number from an enum type (explicit)
json_reverse_iterator operator--(int)
post-decrement (it–)
StringType string_t
a type for a string
static basic_json array(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an array from an initializer list
iterator & operator++()
pre-increment (++it)
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
reference operator+=(const typename object_t::value_type &value)
add an object to an object
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
const_iterator & operator++()
pre-increment (++it)
difference_type operator-(const json_reverse_iterator &other) const
return difference
basic_json<> json
default JSON class
reference front()
access the first element
bool is_array() const noexcept
return whether value is an array
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
json_reverse_iterator(const typename base_iterator::iterator_type &it)
create reverse iterator from iterator
a class to store JSON values
json_reverse_iterator & operator--()
pre-decrement (–it)
void push_back(const typename object_t::value_type &value)
add an object to an object
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
const_iterator cbegin() const
returns a const iterator to the first element
basic_json(const CompatibleObjectType &value)
create an object (implicit)
bool is_string() const noexcept
return whether value is a string
iterator & operator+=(difference_type i)
add to iterator
const PointerType get_ptr() const noexcept
get a pointer value (implicit)
the parser read ] and finished processing a JSON array
const_iterator base_iterator
a mutable random access iterator for the basic_json class
iterator & operator-=(difference_type i)
subtract from iterator
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
reference operator[](const typename object_t::key_type &key)
access specified object element
difference_type operator-(const iterator &other) const
reference value() const
return the value of an iterator
iterator insert(const_iterator pos, size_type count, const basic_json &value)
inserts elements
const_iterator end() const
returns a const iterator to one past the last element
const_iterator(const const_iterator &other) noexcept
copy constructor
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
reference operator+=(const basic_json &value)
add an object to an array
object_t::key_type key() const
return the key of an object iterator
iterator end()
returns an iterator to one past the last element
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
reference operator*()
return a reference to the value pointed to by the iterator
reverse_iterator rend()
returns an iterator to the reverse-end
bool is_object() const noexcept
return whether value is an object
const_iterator operator-(difference_type i)
subtract from iterator
bool is_discarded() const noexcept
return whether value is discarded
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
const_reverse_iterator rend() const
returns a const reverse iterator to one before the first
basic_json(const CompatibleArrayType &value)
create an array (implicit)
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
bool is_boolean() const noexcept
return whether value is a boolean
iterator begin()
returns an iterator to the first element
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
AllocatorType< basic_json > allocator_type
the allocator type
bool is_number_integer() const noexcept
return whether value is an integer number
basic_json(const string_t &value)
create a string (explicit)
iterator operator+(difference_type i)
add to iterator
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
const_iterator()=default
default constructor
the parser read [ and started to process a JSON array
iterator find(typename object_t::key_type key)
find an element in a JSON object
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
iterator & operator--()
pre-decrement (–it)
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
pointer operator->() const
dereference the iterator
discarded by the the parser callback function
const_iterator cend() const
returns a const iterator to one past the last element
typename Base::reference reference
the reference type for the pointed-to element
size_type size() const noexcept
returns the number of elements
static allocator_type get_allocator()
returns the allocator associated with the container
object (unordered set of name/value pairs)
reference at(size_type idx)
access specified array element with bounds checking
the parser read } and finished processing a JSON object
iterator()=default
default constructor
json_reverse_iterator(const base_iterator &it)
create reverse iterator from base class
iterator_wrapper_internal end()
return iterator end (needed for range-based for)
value_t type() const noexcept
return the type of the JSON value (explicit)
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
basic_json(size_type count, const basic_json &value)
construct an array with count copies of given value
object_t::key_type key() const
return the key of an object iterator
bool is_structured() const noexcept
return whether type is structured
namespace for Niels Lohmann
typename basic_json::difference_type difference_type
a type to represent differences between iterators
void swap(array_t &other)
exchanges the values
reverse_iterator rbegin()
returns an iterator to the reverse-beginning
iterator_wrapper_internal begin()
return iterator begin (needed for range-based for)
reference operator[](difference_type n) const
access to successor
std::size_t size_type
a type to represent container sizes
reference operator+=(basic_json &&value)
add an object to an array
const_reverse_iterator rbegin() const
returns a const reverse iterator to the last element
basic_json(const array_t &value)
create an array (explicit)
basic_json(const basic_json &other)
copy constructor
const_iterator operator+(difference_type i)
add to iterator
basic_json(boolean_t value)
create a boolean (explicit)
value_t
the JSON type enumeration
const value_type & const_reference
the type of an element const reference
basic_json(const CompatibleNumberFloatType value) noexcept
create an floating-point number (implicit)
bool is_null() const noexcept
return whether value is null
void swap(string_t &other)
exchanges the values
reference value() const
return the value of an iterator
void push_back(basic_json &&value)
add an object to an array
const_iterator operator--(int)
post-decrement (it–)
void erase(const size_type idx)
remove element from a JSON array given an index
void clear() noexcept
clears the contents
basic_json(const CompatibleStringType &value)
create a string (implicit)
pointer operator->()
dereference the iterator
basic_json value_type
the type of elements in a basic_json container
array (ordered collection of values)
const_reference front() const
access the first element
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
std::ptrdiff_t difference_type
a type to represent differences between iterators
const_iterator & operator+=(difference_type i)
add to iterator
basic_json(std::initializer_list< basic_json > init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
difference_type operator-(const const_iterator &other) const
return difference
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
bool is_number() const noexcept
return whether value is a number
BooleanType boolean_t
a type for a boolean
const_reverse_iterator crend() const
returns a const reverse iterator to one before the first
basic_json() noexcept=default
create a null object (implicitly)
the parser read a key of a value in an object
bool empty() const noexcept
checks whether the container is empty
string_t value(const typename object_t::key_type &key, const char *default_value) const
access specified object element with default value
void swap(reference other) noexcept( std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value )
exchanges the values
basic_json(const object_t &value)
create an object (explicit)
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
const_reverse_iterator crbegin() const
returns a const reverse iterator to the last element
reference value() const
return the value of an iterator
const_iterator(pointer object)
constructor for a given JSON instance
friend bool operator<(const value_t lhs, const value_t rhs)
comparison operator for JSON types
iterator(pointer object) noexcept
constructor for a given JSON instance
bool operator<(const const_iterator &other) const
comparison: smaller
string_t dump(const int indent=-1) const
serialization
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
const_iterator & operator-=(difference_type i)
subtract from iterator
number value (floating-point)
basic_json(const CompatibleNumberIntegerType value) noexcept
create an integer number (implicit)
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
json_reverse_iterator operator++(int)
post-increment (it++)
PointerType get_ptr() noexcept
get a pointer value (implicit)
void push_back(const basic_json &value)
add an object to an array
const_iterator(const iterator &other)
copy constructor given a nonconst iterator
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
InteratorType erase(InteratorType pos)
remove element given an iterator
basic_json(const typename string_t::value_type *value)
create a string (explicit)
bool operator<=(const const_iterator &other) const
comparison: less than or equal
reference back()
access the last element
bool is_number_float() const noexcept
return whether value is a floating-point number
the parser read { and started to process a JSON object
const_iterator operator++(int)
post-increment (it++)
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
iterator(const iterator &other) noexcept
copy constructor
const_reference back() const
access the last element
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
size_type count(typename object_t::key_type key) const
returns the number of occurrences of a key in a JSON object
size_type max_size() const noexcept
returns the maximum possible number of elements
bool operator==(const const_iterator &other) const
comparison: equal
json_reverse_iterator & operator++()
pre-increment (++it)
bool operator>(const const_iterator &other) const
comparison: greater than
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
basic_json(basic_json &&other) noexcept
move constructor
const_iterator begin() const
returns a const iterator to the first element
const_reference at(size_type idx) const
access specified array element with bounds checking
json_reverse_iterator & operator+=(difference_type i)
add to iterator
a const random access iterator for the basic_json class
a template for a reverse iterator class
void swap(object_t &other)
exchanges the values
std::bidirectional_iterator_tag iterator_category
the category of the iterator
bool is_primitive() const noexcept
return whether type is primitive
basic_json(const value_t value)
create an empty value with a given type
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
reference operator[](difference_type n) const
access to successor
NumberIntegerType number_integer_t
a type for a number (integer)
reference operator[](difference_type n) const
access to successor
reference operator*() const
return a reference to the value pointed to by the iterator
iterator insert(const_iterator pos, const basic_json &value)
inserts element
value_type & reference
the type of an element reference
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
the parser finished reading a JSON value
NumberFloatType number_float_t
a type for a number (floating-point)
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
iterator & operator=(iterator other) noexcept( std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value )
copy assignment
reference operator[](size_type idx)
access specified array element
iterator operator--(int)
post-decrement (it–)
json_reverse_iterator operator+(difference_type i) const
add to iterator
parse_event_t
JSON callback events.
iterator operator-(difference_type i)
subtract from iterator
wrapper to access iterator member functions in range-based for