Horizon
Loading...
Searching...
No Matches
json.hpp
1/*
2 __ _____ _____ _____
3 __| | __| | | | JSON for Modern C++
4| | |__ | | | | | | version 3.10.3
5|_____|_____|_____|_|___| https://github.com/nlohmann/json
6
7Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8SPDX-License-Identifier: MIT
9Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>.
10
11Permission is hereby granted, free of charge, to any person obtaining a copy
12of this software and associated documentation files (the "Software"), to deal
13in the Software without restriction, including without limitation the rights
14to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15copies of the Software, and to permit persons to whom the Software is
16furnished to do so, subject to the following conditions:
17
18The above copyright notice and this permission notice shall be included in all
19copies or substantial portions of the Software.
20
21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27SOFTWARE.
28*/
29
30#ifndef INCLUDE_NLOHMANN_JSON_HPP_
31#define INCLUDE_NLOHMANN_JSON_HPP_
32
33#define NLOHMANN_JSON_VERSION_MAJOR 3
34#define NLOHMANN_JSON_VERSION_MINOR 10
35#define NLOHMANN_JSON_VERSION_PATCH 3
36
37#include <algorithm> // all_of, find, for_each
38#include <cstddef> // nullptr_t, ptrdiff_t, size_t
39#include <functional> // hash, less
40#include <initializer_list> // initializer_list
41#ifndef JSON_NO_IO
42 #include <iosfwd> // istream, ostream
43#endif // JSON_NO_IO
44#include <iterator> // random_access_iterator_tag
45#include <memory> // unique_ptr
46#include <numeric> // accumulate
47#include <string> // string, stoi, to_string
48#include <utility> // declval, forward, move, pair, swap
49#include <vector> // vector
50
51#include <nlohmann/adl_serializer.hpp>
52#include <nlohmann/byte_container_with_subtype.hpp>
53#include <nlohmann/detail/conversions/from_json.hpp>
54#include <nlohmann/detail/conversions/to_json.hpp>
55#include <nlohmann/detail/exceptions.hpp>
56#include <nlohmann/detail/hash.hpp>
57#include <nlohmann/detail/input/binary_reader.hpp>
58#include <nlohmann/detail/input/input_adapters.hpp>
59#include <nlohmann/detail/input/lexer.hpp>
60#include <nlohmann/detail/input/parser.hpp>
61#include <nlohmann/detail/iterators/internal_iterator.hpp>
62#include <nlohmann/detail/iterators/iter_impl.hpp>
63#include <nlohmann/detail/iterators/iteration_proxy.hpp>
64#include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
65#include <nlohmann/detail/iterators/primitive_iterator.hpp>
66#include <nlohmann/detail/json_pointer.hpp>
67#include <nlohmann/detail/json_ref.hpp>
68#include <nlohmann/detail/macro_scope.hpp>
69#include <nlohmann/detail/string_escape.hpp>
70#include <nlohmann/detail/meta/cpp_future.hpp>
71#include <nlohmann/detail/meta/type_traits.hpp>
72#include <nlohmann/detail/output/binary_writer.hpp>
73#include <nlohmann/detail/output/output_adapters.hpp>
74#include <nlohmann/detail/output/serializer.hpp>
75#include <nlohmann/detail/value_t.hpp>
76#include <nlohmann/json_fwd.hpp>
77#include <nlohmann/ordered_map.hpp>
78
79#if defined(JSON_HAS_CPP_17)
80 #include <string_view>
81#endif
82
88namespace nlohmann
89{
90
175NLOHMANN_BASIC_JSON_TPL_DECLARATION
176class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
177{
178 private:
179 template<detail::value_t> friend struct detail::external_constructor;
180 friend ::nlohmann::json_pointer<basic_json>;
181
182 template<typename BasicJsonType, typename InputType>
183 friend class ::nlohmann::detail::parser;
184 friend ::nlohmann::detail::serializer<basic_json>;
185 template<typename BasicJsonType>
186 friend class ::nlohmann::detail::iter_impl;
187 template<typename BasicJsonType, typename CharType>
188 friend class ::nlohmann::detail::binary_writer;
189 template<typename BasicJsonType, typename InputType, typename SAX>
190 friend class ::nlohmann::detail::binary_reader;
191 template<typename BasicJsonType>
192 friend class ::nlohmann::detail::json_sax_dom_parser;
193 template<typename BasicJsonType>
194 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
195 friend class ::nlohmann::detail::exception;
196
198 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
199
200 JSON_PRIVATE_UNLESS_TESTED:
201 // convenience aliases for types residing in namespace detail;
203
204 template<typename InputAdapterType>
205 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
206 InputAdapterType adapter,
207 detail::parser_callback_t<basic_json>cb = nullptr,
208 const bool allow_exceptions = true,
209 const bool ignore_comments = false
210 )
211 {
212 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
213 std::move(cb), allow_exceptions, ignore_comments);
214 }
215
216 private:
218 template<typename BasicJsonType>
220 template<typename BasicJsonType>
222 template<typename Iterator>
225
226 template<typename CharType>
227 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
228
229 template<typename InputType>
232
233 JSON_PRIVATE_UNLESS_TESTED:
235
236 public:
237 using value_t = detail::value_t;
240 template<typename T, typename SFINAE>
241 using json_serializer = JSONSerializer<T, SFINAE>;
247 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
248
252
254 // exceptions //
256
260
273
275
276
278 // container types //
280
285
288
293
295 using difference_type = std::ptrdiff_t;
297 using size_type = std::size_t;
298
300 using allocator_type = AllocatorType<basic_json>;
301
303 using pointer = typename std::allocator_traits<allocator_type>::pointer;
305 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
306
315
317
318
323 {
324 return allocator_type();
325 }
326
353 JSON_HEDLEY_WARN_UNUSED_RESULT
355 {
356 basic_json result;
357
358 result["copyright"] = "(C) 2013-2021 Niels Lohmann";
359 result["name"] = "JSON for Modern C++";
360 result["url"] = "https://github.com/nlohmann/json";
361 result["version"]["string"] =
362 std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." +
363 std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." +
364 std::to_string(NLOHMANN_JSON_VERSION_PATCH);
365 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
366 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
367 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
368
369#ifdef _WIN32
370 result["platform"] = "win32";
371#elif defined __linux__
372 result["platform"] = "linux";
373#elif defined __APPLE__
374 result["platform"] = "apple";
375#elif defined __unix__
376 result["platform"] = "unix";
377#else
378 result["platform"] = "unknown";
379#endif
380
381#if defined(__ICC) || defined(__INTEL_COMPILER)
382 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
383#elif defined(__clang__)
384 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
385#elif defined(__GNUC__) || defined(__GNUG__)
386 result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
387#elif defined(__HP_cc) || defined(__HP_aCC)
388 result["compiler"] = "hp"
389#elif defined(__IBMCPP__)
390 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
391#elif defined(_MSC_VER)
392 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
393#elif defined(__PGI)
394 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
395#elif defined(__SUNPRO_CC)
396 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
397#else
398 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
399#endif
400
401#ifdef __cplusplus
402 result["compiler"]["c++"] = std::to_string(__cplusplus);
403#else
404 result["compiler"]["c++"] = "unknown";
405#endif
406 return result;
407 }
408
409
411 // JSON value data types //
413
418
419#if defined(JSON_HAS_CPP_14)
420 // Use transparent comparator if possible, combined with perfect forwarding
421 // on find() and count() calls prevents unnecessary string construction.
422 using object_comparator_t = std::less<>;
423#else
424 using object_comparator_t = std::less<StringType>;
425#endif
426
510 using object_t = ObjectType<StringType,
512 object_comparator_t,
513 AllocatorType<std::pair<const StringType,
514 basic_json>>>;
515
560 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
561
613 using string_t = StringType;
614
639 using boolean_t = BooleanType;
640
711 using number_integer_t = NumberIntegerType;
712
782 using number_unsigned_t = NumberUnsignedType;
783
850 using number_float_t = NumberFloatType;
851
923
924 private:
925
927 template<typename T, typename... Args>
928 JSON_HEDLEY_RETURNS_NON_NULL
929 static T* create(Args&& ... args)
930 {
931 AllocatorType<T> alloc;
932 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
933
934 auto deleter = [&](T * obj)
935 {
936 AllocatorTraits::deallocate(alloc, obj, 1);
937 };
938 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
939 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
940 JSON_ASSERT(obj != nullptr);
941 return obj.release();
942 }
943
945 // JSON value storage //
947
948 JSON_PRIVATE_UNLESS_TESTED:
974 union json_value
975 {
977 object_t* object;
979 array_t* array;
981 string_t* string;
983 binary_t* binary;
985 boolean_t boolean;
987 number_integer_t number_integer;
989 number_unsigned_t number_unsigned;
991 number_float_t number_float;
992
994 json_value() = default;
996 json_value(boolean_t v) noexcept : boolean(v) {}
998 json_value(number_integer_t v) noexcept : number_integer(v) {}
1000 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
1002 json_value(number_float_t v) noexcept : number_float(v) {}
1004 json_value(value_t t)
1005 {
1006 switch (t)
1007 {
1008 case value_t::object:
1009 {
1010 object = create<object_t>();
1011 break;
1012 }
1013
1014 case value_t::array:
1015 {
1016 array = create<array_t>();
1017 break;
1018 }
1019
1020 case value_t::string:
1021 {
1022 string = create<string_t>("");
1023 break;
1024 }
1025
1026 case value_t::binary:
1027 {
1028 binary = create<binary_t>();
1029 break;
1030 }
1031
1032 case value_t::boolean:
1033 {
1034 boolean = boolean_t(false);
1035 break;
1036 }
1037
1038 case value_t::number_integer:
1039 {
1041 break;
1042 }
1043
1044 case value_t::number_unsigned:
1045 {
1047 break;
1048 }
1049
1050 case value_t::number_float:
1051 {
1053 break;
1054 }
1055
1056 case value_t::null:
1057 {
1058 object = nullptr; // silence warning, see #821
1059 break;
1060 }
1061
1062 case value_t::discarded:
1063 default:
1064 {
1065 object = nullptr; // silence warning, see #821
1066 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
1067 {
1068 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.10.3", basic_json())); // LCOV_EXCL_LINE
1069 }
1070 break;
1071 }
1072 }
1073 }
1074
1076 json_value(const string_t& value)
1077 {
1078 string = create<string_t>(value);
1079 }
1080
1082 json_value(string_t&& value)
1083 {
1084 string = create<string_t>(std::move(value));
1085 }
1086
1088 json_value(const object_t& value)
1089 {
1090 object = create<object_t>(value);
1091 }
1092
1094 json_value(object_t&& value)
1095 {
1096 object = create<object_t>(std::move(value));
1097 }
1098
1100 json_value(const array_t& value)
1101 {
1102 array = create<array_t>(value);
1103 }
1104
1106 json_value(array_t&& value)
1107 {
1108 array = create<array_t>(std::move(value));
1109 }
1110
1112 json_value(const typename binary_t::container_type& value)
1113 {
1114 binary = create<binary_t>(value);
1115 }
1116
1118 json_value(typename binary_t::container_type&& value)
1119 {
1120 binary = create<binary_t>(std::move(value));
1121 }
1122
1124 json_value(const binary_t& value)
1125 {
1126 binary = create<binary_t>(value);
1127 }
1128
1130 json_value(binary_t&& value)
1131 {
1132 binary = create<binary_t>(std::move(value));
1133 }
1134
1135 void destroy(value_t t)
1136 {
1137 if (t == value_t::array || t == value_t::object)
1138 {
1139 // flatten the current json_value to a heap-allocated stack
1140 std::vector<basic_json> stack;
1141
1142 // move the top-level items to stack
1143 if (t == value_t::array)
1144 {
1145 stack.reserve(array->size());
1146 std::move(array->begin(), array->end(), std::back_inserter(stack));
1147 }
1148 else
1149 {
1150 stack.reserve(object->size());
1151 for (auto&& it : *object)
1152 {
1153 stack.push_back(std::move(it.second));
1154 }
1155 }
1156
1157 while (!stack.empty())
1158 {
1159 // move the last item to local variable to be processed
1160 basic_json current_item(std::move(stack.back()));
1161 stack.pop_back();
1162
1163 // if current_item is array/object, move
1164 // its children to the stack to be processed later
1165 if (current_item.is_array())
1166 {
1167 std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack));
1168
1169 current_item.m_value.array->clear();
1170 }
1171 else if (current_item.is_object())
1172 {
1173 for (auto&& it : *current_item.m_value.object)
1174 {
1175 stack.push_back(std::move(it.second));
1176 }
1177
1178 current_item.m_value.object->clear();
1179 }
1180
1181 // it's now safe that current_item get destructed
1182 // since it doesn't have any children
1183 }
1184 }
1185
1186 switch (t)
1187 {
1188 case value_t::object:
1189 {
1190 AllocatorType<object_t> alloc;
1191 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
1192 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
1193 break;
1194 }
1195
1196 case value_t::array:
1197 {
1198 AllocatorType<array_t> alloc;
1199 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
1200 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
1201 break;
1202 }
1203
1204 case value_t::string:
1205 {
1206 AllocatorType<string_t> alloc;
1207 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
1208 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
1209 break;
1210 }
1211
1212 case value_t::binary:
1213 {
1214 AllocatorType<binary_t> alloc;
1215 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
1216 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
1217 break;
1218 }
1219
1220 case value_t::null:
1221 case value_t::boolean:
1222 case value_t::number_integer:
1223 case value_t::number_unsigned:
1224 case value_t::number_float:
1225 case value_t::discarded:
1226 default:
1227 {
1228 break;
1229 }
1230 }
1231 }
1232 };
1233
1234 private:
1253 void assert_invariant(bool check_parents = true) const noexcept
1254 {
1255 JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr);
1256 JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr);
1257 JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr);
1258 JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr);
1259
1260#if JSON_DIAGNOSTICS
1261 JSON_TRY
1262 {
1263 // cppcheck-suppress assertWithSideEffect
1264 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
1265 {
1266 return j.m_parent == this;
1267 }));
1268 }
1269 JSON_CATCH(...) {} // LCOV_EXCL_LINE
1270#endif
1271 static_cast<void>(check_parents);
1272 }
1273
1274 void set_parents()
1275 {
1276#if JSON_DIAGNOSTICS
1277 switch (m_type)
1278 {
1279 case value_t::array:
1280 {
1281 for (auto& element : *m_value.array)
1282 {
1283 element.m_parent = this;
1284 }
1285 break;
1286 }
1287
1288 case value_t::object:
1289 {
1290 for (auto& element : *m_value.object)
1291 {
1292 element.second.m_parent = this;
1293 }
1294 break;
1295 }
1296
1297 case value_t::null:
1298 case value_t::string:
1299 case value_t::boolean:
1300 case value_t::number_integer:
1301 case value_t::number_unsigned:
1302 case value_t::number_float:
1303 case value_t::binary:
1304 case value_t::discarded:
1305 default:
1306 break;
1307 }
1308#endif
1309 }
1310
1311 iterator set_parents(iterator it, typename iterator::difference_type count)
1312 {
1313#if JSON_DIAGNOSTICS
1314 for (typename iterator::difference_type i = 0; i < count; ++i)
1315 {
1316 (it + i)->m_parent = this;
1317 }
1318#else
1319 static_cast<void>(count);
1320#endif
1321 return it;
1322 }
1323
1324 reference set_parent(reference j, std::size_t old_capacity = std::size_t(-1))
1325 {
1326#if JSON_DIAGNOSTICS
1327 if (old_capacity != std::size_t(-1))
1328 {
1329 // see https://github.com/nlohmann/json/issues/2838
1330 JSON_ASSERT(type() == value_t::array);
1331 if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
1332 {
1333 // capacity has changed: update all parents
1334 set_parents();
1335 return j;
1336 }
1337 }
1338
1339 // ordered_json uses a vector internally, so pointers could have
1340 // been invalidated; see https://github.com/nlohmann/json/issues/2962
1341#ifdef JSON_HEDLEY_MSVC_VERSION
1342#pragma warning(push )
1343#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
1344#endif
1345 if (detail::is_ordered_map<object_t>::value)
1346 {
1347 set_parents();
1348 return j;
1349 }
1350#ifdef JSON_HEDLEY_MSVC_VERSION
1351#pragma warning( pop )
1352#endif
1353
1354 j.m_parent = this;
1355#else
1356 static_cast<void>(j);
1357 static_cast<void>(old_capacity);
1358#endif
1359 return j;
1360 }
1361
1362 public:
1364 // JSON parser callback //
1366
1383
1433 using parser_callback_t = detail::parser_callback_t<basic_json>;
1434
1436 // constructors //
1438
1443
1475 : m_type(v), m_value(v)
1476 {
1477 assert_invariant();
1478 }
1479
1498 basic_json(std::nullptr_t = nullptr) noexcept
1499 : basic_json(value_t::null)
1500 {
1501 assert_invariant();
1502 }
1503
1566 template < typename CompatibleType,
1567 typename U = detail::uncvref_t<CompatibleType>,
1568 detail::enable_if_t <
1570 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
1571 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
1572 std::forward<CompatibleType>(val))))
1573 {
1574 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
1575 set_parents();
1576 assert_invariant();
1577 }
1578
1605 template < typename BasicJsonType,
1606 detail::enable_if_t <
1607 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
1608 basic_json(const BasicJsonType& val)
1609 {
1610 using other_boolean_t = typename BasicJsonType::boolean_t;
1611 using other_number_float_t = typename BasicJsonType::number_float_t;
1612 using other_number_integer_t = typename BasicJsonType::number_integer_t;
1613 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
1614 using other_string_t = typename BasicJsonType::string_t;
1615 using other_object_t = typename BasicJsonType::object_t;
1616 using other_array_t = typename BasicJsonType::array_t;
1617 using other_binary_t = typename BasicJsonType::binary_t;
1618
1619 switch (val.type())
1620 {
1621 case value_t::boolean:
1622 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
1623 break;
1624 case value_t::number_float:
1625 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
1626 break;
1627 case value_t::number_integer:
1628 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
1629 break;
1630 case value_t::number_unsigned:
1631 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
1632 break;
1633 case value_t::string:
1634 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
1635 break;
1636 case value_t::object:
1637 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
1638 break;
1639 case value_t::array:
1640 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
1641 break;
1642 case value_t::binary:
1643 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
1644 break;
1645 case value_t::null:
1646 *this = nullptr;
1647 break;
1648 case value_t::discarded:
1649 m_type = value_t::discarded;
1650 break;
1651 default: // LCOV_EXCL_LINE
1652 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
1653 }
1654 set_parents();
1655 assert_invariant();
1656 }
1657
1733 bool type_deduction = true,
1734 value_t manual_type = value_t::array)
1735 {
1736 // check if each element is an array with two elements whose first
1737 // element is a string
1738 bool is_an_object = std::all_of(init.begin(), init.end(),
1739 [](const detail::json_ref<basic_json>& element_ref)
1740 {
1741 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string();
1742 });
1743
1744 // adjust type if type deduction is not wanted
1745 if (!type_deduction)
1746 {
1747 // if array is wanted, do not create an object though possible
1748 if (manual_type == value_t::array)
1749 {
1750 is_an_object = false;
1751 }
1752
1753 // if object is wanted but impossible, throw an exception
1754 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
1755 {
1756 JSON_THROW(type_error::create(301, "cannot create object from initializer list", basic_json()));
1757 }
1758 }
1759
1760 if (is_an_object)
1761 {
1762 // the initializer list is a list of pairs -> create object
1763 m_type = value_t::object;
1764 m_value = value_t::object;
1765
1766 for (auto& element_ref : init)
1767 {
1768 auto element = element_ref.moved_or_copied();
1770 std::move(*((*element.m_value.array)[0].m_value.string)),
1771 std::move((*element.m_value.array)[1]));
1772 }
1773 }
1774 else
1775 {
1776 // the initializer list describes an array -> create array
1777 m_type = value_t::array;
1778 m_value.array = create<array_t>(init.begin(), init.end());
1779 }
1780
1781 set_parents();
1782 assert_invariant();
1783 }
1784
1812 JSON_HEDLEY_WARN_UNUSED_RESULT
1813 static basic_json binary(const typename binary_t::container_type& init)
1814 {
1815 auto res = basic_json();
1816 res.m_type = value_t::binary;
1817 res.m_value = init;
1818 return res;
1819 }
1820
1849 JSON_HEDLEY_WARN_UNUSED_RESULT
1850 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
1851 {
1852 auto res = basic_json();
1853 res.m_type = value_t::binary;
1854 res.m_value = binary_t(init, subtype);
1855 return res;
1856 }
1857
1859 JSON_HEDLEY_WARN_UNUSED_RESULT
1861 {
1862 auto res = basic_json();
1863 res.m_type = value_t::binary;
1864 res.m_value = std::move(init);
1865 return res;
1866 }
1867
1869 JSON_HEDLEY_WARN_UNUSED_RESULT
1870 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
1871 {
1872 auto res = basic_json();
1873 res.m_type = value_t::binary;
1874 res.m_value = binary_t(std::move(init), subtype);
1875 return res;
1876 }
1877
1915 JSON_HEDLEY_WARN_UNUSED_RESULT
1917 {
1918 return basic_json(init, false, value_t::array);
1919 }
1920
1959 JSON_HEDLEY_WARN_UNUSED_RESULT
1961 {
1962 return basic_json(init, false, value_t::object);
1963 }
1964
1988 : m_type(value_t::array)
1989 {
1990 m_value.array = create<array_t>(cnt, val);
1991 set_parents();
1992 assert_invariant();
1993 }
1994
2050 template < class InputIT, typename std::enable_if <
2051 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
2052 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
2053 basic_json(InputIT first, InputIT last)
2054 {
2055 JSON_ASSERT(first.m_object != nullptr);
2056 JSON_ASSERT(last.m_object != nullptr);
2057
2058 // make sure iterator fits the current value
2059 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
2060 {
2061 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", basic_json()));
2062 }
2063
2064 // copy type from first iterator
2065 m_type = first.m_object->m_type;
2066
2067 // check if iterator range is complete for primitive values
2068 switch (m_type)
2069 {
2070 case value_t::boolean:
2071 case value_t::number_float:
2072 case value_t::number_integer:
2073 case value_t::number_unsigned:
2074 case value_t::string:
2075 {
2076 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
2077 || !last.m_it.primitive_iterator.is_end()))
2078 {
2079 JSON_THROW(invalid_iterator::create(204, "iterators out of range", *first.m_object));
2080 }
2081 break;
2082 }
2083
2084 case value_t::null:
2085 case value_t::object:
2086 case value_t::array:
2087 case value_t::binary:
2088 case value_t::discarded:
2089 default:
2090 break;
2091 }
2092
2093 switch (m_type)
2094 {
2095 case value_t::number_integer:
2096 {
2097 m_value.number_integer = first.m_object->m_value.number_integer;
2098 break;
2099 }
2100
2101 case value_t::number_unsigned:
2102 {
2103 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
2104 break;
2105 }
2106
2107 case value_t::number_float:
2108 {
2109 m_value.number_float = first.m_object->m_value.number_float;
2110 break;
2111 }
2112
2113 case value_t::boolean:
2114 {
2115 m_value.boolean = first.m_object->m_value.boolean;
2116 break;
2117 }
2118
2119 case value_t::string:
2120 {
2121 m_value = *first.m_object->m_value.string;
2122 break;
2123 }
2124
2125 case value_t::object:
2126 {
2127 m_value.object = create<object_t>(first.m_it.object_iterator,
2128 last.m_it.object_iterator);
2129 break;
2130 }
2131
2132 case value_t::array:
2133 {
2134 m_value.array = create<array_t>(first.m_it.array_iterator,
2135 last.m_it.array_iterator);
2136 break;
2137 }
2138
2139 case value_t::binary:
2140 {
2141 m_value = *first.m_object->m_value.binary;
2142 break;
2143 }
2144
2145 case value_t::null:
2146 case value_t::discarded:
2147 default:
2148 JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + std::string(first.m_object->type_name()), *first.m_object));
2149 }
2150
2151 set_parents();
2152 assert_invariant();
2153 }
2154
2155
2157 // other constructors and destructor //
2159
2160 template<typename JsonRef,
2161 detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
2162 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
2163 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
2164
2191 : m_type(other.m_type)
2192 {
2193 // check of passed value is valid
2194 other.assert_invariant();
2195
2196 switch (m_type)
2197 {
2198 case value_t::object:
2199 {
2200 m_value = *other.m_value.object;
2201 break;
2202 }
2203
2204 case value_t::array:
2205 {
2206 m_value = *other.m_value.array;
2207 break;
2208 }
2209
2210 case value_t::string:
2211 {
2212 m_value = *other.m_value.string;
2213 break;
2214 }
2215
2216 case value_t::boolean:
2217 {
2218 m_value = other.m_value.boolean;
2219 break;
2220 }
2221
2222 case value_t::number_integer:
2223 {
2224 m_value = other.m_value.number_integer;
2225 break;
2226 }
2227
2228 case value_t::number_unsigned:
2229 {
2230 m_value = other.m_value.number_unsigned;
2231 break;
2232 }
2233
2234 case value_t::number_float:
2235 {
2236 m_value = other.m_value.number_float;
2237 break;
2238 }
2239
2240 case value_t::binary:
2241 {
2242 m_value = *other.m_value.binary;
2243 break;
2244 }
2245
2246 case value_t::null:
2247 case value_t::discarded:
2248 default:
2249 break;
2250 }
2251
2252 set_parents();
2253 assert_invariant();
2254 }
2255
2282 basic_json(basic_json&& other) noexcept
2283 : m_type(std::move(other.m_type)),
2284 m_value(std::move(other.m_value))
2285 {
2286 // check that passed value is valid
2287 other.assert_invariant(false);
2288
2289 // invalidate payload
2290 other.m_type = value_t::null;
2291 other.m_value = {};
2292
2293 set_parents();
2294 assert_invariant();
2295 }
2296
2321 std::is_nothrow_move_constructible<value_t>::value&&
2322 std::is_nothrow_move_assignable<value_t>::value&&
2323 std::is_nothrow_move_constructible<json_value>::value&&
2324 std::is_nothrow_move_assignable<json_value>::value
2325 )
2326 {
2327 // check that passed value is valid
2328 other.assert_invariant();
2329
2330 using std::swap;
2331 swap(m_type, other.m_type);
2332 swap(m_value, other.m_value);
2333
2334 set_parents();
2335 assert_invariant();
2336 return *this;
2337 }
2338
2354 ~basic_json() noexcept
2355 {
2356 assert_invariant(false);
2357 m_value.destroy(m_type);
2358 }
2359
2361
2362 public:
2364 // object inspection //
2366
2370
2418 string_t dump(const int indent = -1,
2419 const char indent_char = ' ',
2420 const bool ensure_ascii = false,
2421 const error_handler_t error_handler = error_handler_t::strict) const
2422 {
2423 string_t result;
2424 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
2425
2426 if (indent >= 0)
2427 {
2428 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
2429 }
2430 else
2431 {
2432 s.dump(*this, false, ensure_ascii, 0);
2433 }
2434
2435 return result;
2436 }
2437
2471 constexpr value_t type() const noexcept
2472 {
2473 return m_type;
2474 }
2475
2502 constexpr bool is_primitive() const noexcept
2503 {
2504 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
2505 }
2506
2529 constexpr bool is_structured() const noexcept
2530 {
2531 return is_array() || is_object();
2532 }
2533
2551 constexpr bool is_null() const noexcept
2552 {
2553 return m_type == value_t::null;
2554 }
2555
2573 constexpr bool is_boolean() const noexcept
2574 {
2575 return m_type == value_t::boolean;
2576 }
2577
2603 constexpr bool is_number() const noexcept
2604 {
2605 return is_number_integer() || is_number_float();
2606 }
2607
2632 constexpr bool is_number_integer() const noexcept
2633 {
2634 return m_type == value_t::number_integer || m_type == value_t::number_unsigned;
2635 }
2636
2660 constexpr bool is_number_unsigned() const noexcept
2661 {
2662 return m_type == value_t::number_unsigned;
2663 }
2664
2688 constexpr bool is_number_float() const noexcept
2689 {
2690 return m_type == value_t::number_float;
2691 }
2692
2710 constexpr bool is_object() const noexcept
2711 {
2712 return m_type == value_t::object;
2713 }
2714
2732 constexpr bool is_array() const noexcept
2733 {
2734 return m_type == value_t::array;
2735 }
2736
2754 constexpr bool is_string() const noexcept
2755 {
2756 return m_type == value_t::string;
2757 }
2758
2776 constexpr bool is_binary() const noexcept
2777 {
2778 return m_type == value_t::binary;
2779 }
2780
2803 constexpr bool is_discarded() const noexcept
2804 {
2805 return m_type == value_t::discarded;
2806 }
2807
2829 constexpr operator value_t() const noexcept
2830 {
2831 return m_type;
2832 }
2833
2835
2836 private:
2838 // value access //
2840
2842 boolean_t get_impl(boolean_t* /*unused*/) const
2843 {
2844 if (JSON_HEDLEY_LIKELY(is_boolean()))
2845 {
2846 return m_value.boolean;
2847 }
2848
2849 JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()), *this));
2850 }
2851
2853 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
2854 {
2855 return is_object() ? m_value.object : nullptr;
2856 }
2857
2859 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
2860 {
2861 return is_object() ? m_value.object : nullptr;
2862 }
2863
2865 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
2866 {
2867 return is_array() ? m_value.array : nullptr;
2868 }
2869
2871 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
2872 {
2873 return is_array() ? m_value.array : nullptr;
2874 }
2875
2877 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
2878 {
2879 return is_string() ? m_value.string : nullptr;
2880 }
2881
2883 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
2884 {
2885 return is_string() ? m_value.string : nullptr;
2886 }
2887
2889 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
2890 {
2891 return is_boolean() ? &m_value.boolean : nullptr;
2892 }
2893
2895 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
2896 {
2897 return is_boolean() ? &m_value.boolean : nullptr;
2898 }
2899
2901 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
2902 {
2903 return is_number_integer() ? &m_value.number_integer : nullptr;
2904 }
2905
2907 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
2908 {
2909 return is_number_integer() ? &m_value.number_integer : nullptr;
2910 }
2911
2913 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
2914 {
2915 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2916 }
2917
2919 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
2920 {
2921 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2922 }
2923
2925 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
2926 {
2927 return is_number_float() ? &m_value.number_float : nullptr;
2928 }
2929
2931 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
2932 {
2933 return is_number_float() ? &m_value.number_float : nullptr;
2934 }
2935
2937 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
2938 {
2939 return is_binary() ? m_value.binary : nullptr;
2940 }
2941
2943 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
2944 {
2945 return is_binary() ? m_value.binary : nullptr;
2946 }
2947
2959 template<typename ReferenceType, typename ThisType>
2960 static ReferenceType get_ref_impl(ThisType& obj)
2961 {
2962 // delegate the call to get_ptr<>()
2963 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
2964
2965 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
2966 {
2967 return *ptr;
2968 }
2969
2970 JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name()), obj));
2971 }
2972
2973 public:
2977
3004 template<typename PointerType, typename std::enable_if<
3005 std::is_pointer<PointerType>::value, int>::type = 0>
3006 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
3007 {
3008 // delegate the call to get_impl_ptr<>()
3009 return get_impl_ptr(static_cast<PointerType>(nullptr));
3010 }
3011
3016 template < typename PointerType, typename std::enable_if <
3017 std::is_pointer<PointerType>::value&&
3018 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
3019 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
3020 {
3021 // delegate the call to get_impl_ptr<>() const
3022 return get_impl_ptr(static_cast<PointerType>(nullptr));
3023 }
3024
3025 private:
3064 template < typename ValueType,
3065 detail::enable_if_t <
3068 int > = 0 >
3069 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
3070 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
3071 {
3072 ValueType ret{};
3073 JSONSerializer<ValueType>::from_json(*this, ret);
3074 return ret;
3075 }
3076
3107 template < typename ValueType,
3108 detail::enable_if_t <
3109 detail::has_non_default_from_json<basic_json_t, ValueType>::value,
3110 int > = 0 >
3111 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
3112 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
3113 {
3114 return JSONSerializer<ValueType>::from_json(*this);
3115 }
3116
3132 template < typename BasicJsonType,
3133 detail::enable_if_t <
3134 detail::is_basic_json<BasicJsonType>::value,
3135 int > = 0 >
3136 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
3137 {
3138 return *this;
3139 }
3140
3155 template<typename BasicJsonType,
3156 detail::enable_if_t<
3157 std::is_same<BasicJsonType, basic_json_t>::value,
3158 int> = 0>
3159 basic_json get_impl(detail::priority_tag<3> /*unused*/) const
3160 {
3161 return *this;
3162 }
3163
3168 template<typename PointerType,
3169 detail::enable_if_t<
3170 std::is_pointer<PointerType>::value,
3171 int> = 0>
3172 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
3173 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
3174 {
3175 // delegate the call to get_ptr
3176 return get_ptr<PointerType>();
3177 }
3178
3179 public:
3203 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
3204#if defined(JSON_HAS_CPP_14)
3205 constexpr
3206#endif
3207 auto get() const noexcept(
3208 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
3209 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
3210 {
3211 // we cannot static_assert on ValueTypeCV being non-const, because
3212 // there is support for get<const basic_json_t>(), which is why we
3213 // still need the uncvref
3214 static_assert(!std::is_reference<ValueTypeCV>::value,
3215 "get() cannot be used with reference types, you might want to use get_ref()");
3216 return get_impl<ValueType>(detail::priority_tag<4> {});
3217 }
3218
3246 template<typename PointerType, typename std::enable_if<
3247 std::is_pointer<PointerType>::value, int>::type = 0>
3248 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
3249 {
3250 // delegate the call to get_ptr
3251 return get_ptr<PointerType>();
3252 }
3253
3287 template < typename ValueType,
3288 detail::enable_if_t <
3291 int > = 0 >
3292 ValueType & get_to(ValueType& v) const noexcept(noexcept(
3293 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
3294 {
3295 JSONSerializer<ValueType>::from_json(*this, v);
3296 return v;
3297 }
3298
3299 // specialization to allow to call get_to with a basic_json value
3300 // see https://github.com/nlohmann/json/issues/2175
3301 template<typename ValueType,
3302 detail::enable_if_t <
3304 int> = 0>
3305 ValueType & get_to(ValueType& v) const
3306 {
3307 v = *this;
3308 return v;
3309 }
3310
3311 template <
3312 typename T, std::size_t N,
3313 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
3314 detail::enable_if_t <
3315 detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
3316 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
3317 noexcept(noexcept(JSONSerializer<Array>::from_json(
3318 std::declval<const basic_json_t&>(), v)))
3319 {
3320 JSONSerializer<Array>::from_json(*this, v);
3321 return v;
3322 }
3323
3350 template<typename ReferenceType, typename std::enable_if<
3351 std::is_reference<ReferenceType>::value, int>::type = 0>
3352 ReferenceType get_ref()
3353 {
3354 // delegate call to get_ref_impl
3355 return get_ref_impl<ReferenceType>(*this);
3356 }
3357
3362 template < typename ReferenceType, typename std::enable_if <
3363 std::is_reference<ReferenceType>::value&&
3364 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
3365 ReferenceType get_ref() const
3366 {
3367 // delegate call to get_ref_impl
3368 return get_ref_impl<ReferenceType>(*this);
3369 }
3370
3400 template < typename ValueType, typename std::enable_if <
3407
3408#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
3410#endif
3412 >::value, int >::type = 0 >
3413 JSON_EXPLICIT operator ValueType() const
3414 {
3415 // delegate the call to get<>() const
3416 return get<ValueType>();
3417 }
3418
3429 {
3430 if (!is_binary())
3431 {
3432 JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this));
3433 }
3434
3435 return *get_ptr<binary_t*>();
3436 }
3437
3439 const binary_t& get_binary() const
3440 {
3441 if (!is_binary())
3442 {
3443 JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this));
3444 }
3445
3446 return *get_ptr<const binary_t*>();
3447 }
3448
3450
3451
3453 // element access //
3455
3459
3487 {
3488 // at only works for arrays
3489 if (JSON_HEDLEY_LIKELY(is_array()))
3490 {
3491 JSON_TRY
3492 {
3493 return set_parent(m_value.array->at(idx));
3494 }
3495 JSON_CATCH (std::out_of_range&)
3496 {
3497 // create better exception explanation
3498 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
3499 }
3500 }
3501 else
3502 {
3503 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
3504 }
3505 }
3506
3534 {
3535 // at only works for arrays
3536 if (JSON_HEDLEY_LIKELY(is_array()))
3537 {
3538 JSON_TRY
3539 {
3540 return m_value.array->at(idx);
3541 }
3542 JSON_CATCH (std::out_of_range&)
3543 {
3544 // create better exception explanation
3545 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
3546 }
3547 }
3548 else
3549 {
3550 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
3551 }
3552 }
3553
3584 reference at(const typename object_t::key_type& key)
3585 {
3586 // at only works for objects
3587 if (JSON_HEDLEY_LIKELY(is_object()))
3588 {
3589 JSON_TRY
3590 {
3591 return set_parent(m_value.object->at(key));
3592 }
3593 JSON_CATCH (std::out_of_range&)
3594 {
3595 // create better exception explanation
3596 JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this));
3597 }
3598 }
3599 else
3600 {
3601 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
3602 }
3603 }
3604
3635 const_reference at(const typename object_t::key_type& key) const
3636 {
3637 // at only works for objects
3638 if (JSON_HEDLEY_LIKELY(is_object()))
3639 {
3640 JSON_TRY
3641 {
3642 return m_value.object->at(key);
3643 }
3644 JSON_CATCH (std::out_of_range&)
3645 {
3646 // create better exception explanation
3647 JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this));
3648 }
3649 }
3650 else
3651 {
3652 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
3653 }
3654 }
3655
3682 {
3683 // implicitly convert null value to an empty array
3684 if (is_null())
3685 {
3686 m_type = value_t::array;
3687 m_value.array = create<array_t>();
3688 assert_invariant();
3689 }
3690
3691 // operator[] only works for arrays
3692 if (JSON_HEDLEY_LIKELY(is_array()))
3693 {
3694 // fill up array with null values if given idx is outside range
3695 if (idx >= m_value.array->size())
3696 {
3697#if JSON_DIAGNOSTICS
3698 // remember array size & capacity before resizing
3699 const auto old_size = m_value.array->size();
3700 const auto old_capacity = m_value.array->capacity();
3701#endif
3702 m_value.array->resize(idx + 1);
3703
3704#if JSON_DIAGNOSTICS
3705 if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
3706 {
3707 // capacity has changed: update all parents
3708 set_parents();
3709 }
3710 else
3711 {
3712 // set parent for values added above
3713 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
3714 }
3715#endif
3716 assert_invariant();
3717 }
3718
3719 return m_value.array->operator[](idx);
3720 }
3721
3722 JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this));
3723 }
3724
3745 {
3746 // const operator[] only works for arrays
3747 if (JSON_HEDLEY_LIKELY(is_array()))
3748 {
3749 return m_value.array->operator[](idx);
3750 }
3751
3752 JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this));
3753 }
3754
3782 reference operator[](const typename object_t::key_type& key)
3783 {
3784 // implicitly convert null value to an empty object
3785 if (is_null())
3786 {
3787 m_type = value_t::object;
3788 m_value.object = create<object_t>();
3789 assert_invariant();
3790 }
3791
3792 // operator[] only works for objects
3793 if (JSON_HEDLEY_LIKELY(is_object()))
3794 {
3795 return set_parent(m_value.object->operator[](key));
3796 }
3797
3798 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
3799 }
3800
3831 const_reference operator[](const typename object_t::key_type& key) const
3832 {
3833 // const operator[] only works for objects
3834 if (JSON_HEDLEY_LIKELY(is_object()))
3835 {
3836 JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
3837 return m_value.object->find(key)->second;
3838 }
3839
3840 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
3841 }
3842
3870 template<typename T>
3871 JSON_HEDLEY_NON_NULL(2)
3872 reference operator[](T* key)
3873 {
3874 // implicitly convert null to object
3875 if (is_null())
3876 {
3877 m_type = value_t::object;
3878 m_value = value_t::object;
3879 assert_invariant();
3880 }
3881
3882 // at only works for objects
3883 if (JSON_HEDLEY_LIKELY(is_object()))
3884 {
3885 return set_parent(m_value.object->operator[](key));
3886 }
3887
3888 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
3889 }
3890
3921 template<typename T>
3922 JSON_HEDLEY_NON_NULL(2)
3923 const_reference operator[](T* key) const
3924 {
3925 // at only works for objects
3926 if (JSON_HEDLEY_LIKELY(is_object()))
3927 {
3928 JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
3929 return m_value.object->find(key)->second;
3930 }
3931
3932 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
3933 }
3934
3985 // using std::is_convertible in a std::enable_if will fail when using explicit conversions
3986 template < class ValueType, typename std::enable_if <
3988 && !std::is_same<value_t, ValueType>::value, int >::type = 0 >
3989 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
3990 {
3991 // at only works for objects
3992 if (JSON_HEDLEY_LIKELY(is_object()))
3993 {
3994 // if key is found, return value and given default value otherwise
3995 const auto it = find(key);
3996 if (it != end())
3997 {
3998 return it->template get<ValueType>();
3999 }
4000
4001 return default_value;
4002 }
4003
4004 JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this));
4005 }
4006
4011 string_t value(const typename object_t::key_type& key, const char* default_value) const
4012 {
4013 return value(key, string_t(default_value));
4014 }
4015
4059 template<class ValueType, typename std::enable_if<
4061 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
4062 {
4063 // at only works for objects
4064 if (JSON_HEDLEY_LIKELY(is_object()))
4065 {
4066 // if pointer resolves a value, return it or use default value
4067 JSON_TRY
4068 {
4069 return ptr.get_checked(this).template get<ValueType>();
4070 }
4071 JSON_INTERNAL_CATCH (out_of_range&)
4072 {
4073 return default_value;
4074 }
4075 }
4076
4077 JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this));
4078 }
4079
4084 JSON_HEDLEY_NON_NULL(3)
4085 string_t value(const json_pointer& ptr, const char* default_value) const
4086 {
4087 return value(ptr, string_t(default_value));
4088 }
4089
4116 {
4117 return *begin();
4118 }
4119
4124 {
4125 return *cbegin();
4126 }
4127
4160 {
4161 auto tmp = end();
4162 --tmp;
4163 return *tmp;
4164 }
4165
4170 {
4171 auto tmp = cend();
4172 --tmp;
4173 return *tmp;
4174 }
4175
4222 template < class IteratorType, typename std::enable_if <
4223 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
4224 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
4225 = 0 >
4226 IteratorType erase(IteratorType pos)
4227 {
4228 // make sure iterator fits the current value
4229 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
4230 {
4231 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
4232 }
4233
4234 IteratorType result = end();
4235
4236 switch (m_type)
4237 {
4238 case value_t::boolean:
4239 case value_t::number_float:
4240 case value_t::number_integer:
4241 case value_t::number_unsigned:
4242 case value_t::string:
4243 case value_t::binary:
4244 {
4245 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
4246 {
4247 JSON_THROW(invalid_iterator::create(205, "iterator out of range", *this));
4248 }
4249
4250 if (is_string())
4251 {
4252 AllocatorType<string_t> alloc;
4253 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
4254 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
4255 m_value.string = nullptr;
4256 }
4257 else if (is_binary())
4258 {
4259 AllocatorType<binary_t> alloc;
4260 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
4261 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
4262 m_value.binary = nullptr;
4263 }
4264
4265 m_type = value_t::null;
4266 assert_invariant();
4267 break;
4268 }
4269
4270 case value_t::object:
4271 {
4272 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
4273 break;
4274 }
4275
4276 case value_t::array:
4277 {
4278 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
4279 break;
4280 }
4281
4282 case value_t::null:
4283 case value_t::discarded:
4284 default:
4285 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
4286 }
4287
4288 return result;
4289 }
4290
4337 template < class IteratorType, typename std::enable_if <
4338 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
4339 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
4340 = 0 >
4341 IteratorType erase(IteratorType first, IteratorType last)
4342 {
4343 // make sure iterator fits the current value
4344 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
4345 {
4346 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", *this));
4347 }
4348
4349 IteratorType result = end();
4350
4351 switch (m_type)
4352 {
4353 case value_t::boolean:
4354 case value_t::number_float:
4355 case value_t::number_integer:
4356 case value_t::number_unsigned:
4357 case value_t::string:
4358 case value_t::binary:
4359 {
4360 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
4361 || !last.m_it.primitive_iterator.is_end()))
4362 {
4363 JSON_THROW(invalid_iterator::create(204, "iterators out of range", *this));
4364 }
4365
4366 if (is_string())
4367 {
4368 AllocatorType<string_t> alloc;
4369 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
4370 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
4371 m_value.string = nullptr;
4372 }
4373 else if (is_binary())
4374 {
4375 AllocatorType<binary_t> alloc;
4376 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
4377 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
4378 m_value.binary = nullptr;
4379 }
4380
4381 m_type = value_t::null;
4382 assert_invariant();
4383 break;
4384 }
4385
4386 case value_t::object:
4387 {
4388 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4389 last.m_it.object_iterator);
4390 break;
4391 }
4392
4393 case value_t::array:
4394 {
4395 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4396 last.m_it.array_iterator);
4397 break;
4398 }
4399
4400 case value_t::null:
4401 case value_t::discarded:
4402 default:
4403 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
4404 }
4405
4406 return result;
4407 }
4408
4438 size_type erase(const typename object_t::key_type& key)
4439 {
4440 // this erase only works for objects
4441 if (JSON_HEDLEY_LIKELY(is_object()))
4442 {
4443 return m_value.object->erase(key);
4444 }
4445
4446 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
4447 }
4448
4473 void erase(const size_type idx)
4474 {
4475 // this erase only works for arrays
4476 if (JSON_HEDLEY_LIKELY(is_array()))
4477 {
4478 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
4479 {
4480 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
4481 }
4482
4483 m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
4484 }
4485 else
4486 {
4487 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
4488 }
4489 }
4490
4492
4493
4495 // lookup //
4497
4500
4525 template<typename KeyT>
4526 iterator find(KeyT&& key)
4527 {
4528 auto result = end();
4529
4530 if (is_object())
4531 {
4532 result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
4533 }
4534
4535 return result;
4536 }
4537
4542 template<typename KeyT>
4543 const_iterator find(KeyT&& key) const
4544 {
4545 auto result = cend();
4546
4547 if (is_object())
4548 {
4549 result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
4550 }
4551
4552 return result;
4553 }
4554
4576 template<typename KeyT>
4577 size_type count(KeyT&& key) const
4578 {
4579 // return 0 for all nonobject types
4580 return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
4581 }
4582
4608 template < typename KeyT, typename std::enable_if <
4609 !std::is_same<typename std::decay<KeyT>::type, json_pointer>::value, int >::type = 0 >
4610 bool contains(KeyT && key) const
4611 {
4612 return is_object() && m_value.object->find(std::forward<KeyT>(key)) != m_value.object->end();
4613 }
4614
4641 bool contains(const json_pointer& ptr) const
4642 {
4643 return ptr.contains(this);
4644 }
4645
4647
4648
4650 // iterators //
4652
4655
4680 iterator begin() noexcept
4681 {
4682 iterator result(this);
4683 result.set_begin();
4684 return result;
4685 }
4686
4690 const_iterator begin() const noexcept
4691 {
4692 return cbegin();
4693 }
4694
4720 const_iterator cbegin() const noexcept
4721 {
4722 const_iterator result(this);
4723 result.set_begin();
4724 return result;
4725 }
4726
4751 iterator end() noexcept
4752 {
4753 iterator result(this);
4754 result.set_end();
4755 return result;
4756 }
4757
4761 const_iterator end() const noexcept
4762 {
4763 return cend();
4764 }
4765
4791 const_iterator cend() const noexcept
4792 {
4793 const_iterator result(this);
4794 result.set_end();
4795 return result;
4796 }
4797
4822 {
4823 return reverse_iterator(end());
4824 }
4825
4830 {
4831 return crbegin();
4832 }
4833
4859 {
4860 return reverse_iterator(begin());
4861 }
4862
4867 {
4868 return crend();
4869 }
4870
4896 {
4897 return const_reverse_iterator(cend());
4898 }
4899
4925 {
4927 }
4928
4929 public:
4987 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
4989 {
4990 return ref.items();
4991 }
4992
4996 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
4998 {
4999 return ref.items();
5000 }
5001
5071 {
5072 return iteration_proxy<iterator>(*this);
5073 }
5074
5079 {
5080 return iteration_proxy<const_iterator>(*this);
5081 }
5082
5084
5085
5087 // capacity //
5089
5092
5135 bool empty() const noexcept
5136 {
5137 switch (m_type)
5138 {
5139 case value_t::null:
5140 {
5141 // null values are empty
5142 return true;
5143 }
5144
5145 case value_t::array:
5146 {
5147 // delegate call to array_t::empty()
5148 return m_value.array->empty();
5149 }
5150
5151 case value_t::object:
5152 {
5153 // delegate call to object_t::empty()
5154 return m_value.object->empty();
5155 }
5156
5157 case value_t::string:
5158 case value_t::boolean:
5159 case value_t::number_integer:
5160 case value_t::number_unsigned:
5161 case value_t::number_float:
5162 case value_t::binary:
5163 case value_t::discarded:
5164 default:
5165 {
5166 // all other types are nonempty
5167 return false;
5168 }
5169 }
5170 }
5171
5215 size_type size() const noexcept
5216 {
5217 switch (m_type)
5218 {
5219 case value_t::null:
5220 {
5221 // null values are empty
5222 return 0;
5223 }
5224
5225 case value_t::array:
5226 {
5227 // delegate call to array_t::size()
5228 return m_value.array->size();
5229 }
5230
5231 case value_t::object:
5232 {
5233 // delegate call to object_t::size()
5234 return m_value.object->size();
5235 }
5236
5237 case value_t::string:
5238 case value_t::boolean:
5239 case value_t::number_integer:
5240 case value_t::number_unsigned:
5241 case value_t::number_float:
5242 case value_t::binary:
5243 case value_t::discarded:
5244 default:
5245 {
5246 // all other types have size 1
5247 return 1;
5248 }
5249 }
5250 }
5251
5293 size_type max_size() const noexcept
5294 {
5295 switch (m_type)
5296 {
5297 case value_t::array:
5298 {
5299 // delegate call to array_t::max_size()
5300 return m_value.array->max_size();
5301 }
5302
5303 case value_t::object:
5304 {
5305 // delegate call to object_t::max_size()
5306 return m_value.object->max_size();
5307 }
5308
5309 case value_t::null:
5310 case value_t::string:
5311 case value_t::boolean:
5312 case value_t::number_integer:
5313 case value_t::number_unsigned:
5314 case value_t::number_float:
5315 case value_t::binary:
5316 case value_t::discarded:
5317 default:
5318 {
5319 // all other types have max_size() == size()
5320 return size();
5321 }
5322 }
5323 }
5324
5326
5327
5329 // modifiers //
5331
5334
5372 void clear() noexcept
5373 {
5374 switch (m_type)
5375 {
5376 case value_t::number_integer:
5377 {
5378 m_value.number_integer = 0;
5379 break;
5380 }
5381
5382 case value_t::number_unsigned:
5383 {
5384 m_value.number_unsigned = 0;
5385 break;
5386 }
5387
5388 case value_t::number_float:
5389 {
5390 m_value.number_float = 0.0;
5391 break;
5392 }
5393
5394 case value_t::boolean:
5395 {
5396 m_value.boolean = false;
5397 break;
5398 }
5399
5400 case value_t::string:
5401 {
5402 m_value.string->clear();
5403 break;
5404 }
5405
5406 case value_t::binary:
5407 {
5408 m_value.binary->clear();
5409 break;
5410 }
5411
5412 case value_t::array:
5413 {
5414 m_value.array->clear();
5415 break;
5416 }
5417
5418 case value_t::object:
5419 {
5420 m_value.object->clear();
5421 break;
5422 }
5423
5424 case value_t::null:
5425 case value_t::discarded:
5426 default:
5427 break;
5428 }
5429 }
5430
5452 {
5453 // push_back only works for null objects or arrays
5454 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
5455 {
5456 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
5457 }
5458
5459 // transform null object into an array
5460 if (is_null())
5461 {
5462 m_type = value_t::array;
5463 m_value = value_t::array;
5464 assert_invariant();
5465 }
5466
5467 // add element to array (move semantics)
5468 const auto old_capacity = m_value.array->capacity();
5469 m_value.array->push_back(std::move(val));
5470 set_parent(m_value.array->back(), old_capacity);
5471 // if val is moved from, basic_json move constructor marks it null so we do not call the destructor
5472 }
5473
5479 {
5480 push_back(std::move(val));
5481 return *this;
5482 }
5483
5488 void push_back(const basic_json& val)
5489 {
5490 // push_back only works for null objects or arrays
5491 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
5492 {
5493 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
5494 }
5495
5496 // transform null object into an array
5497 if (is_null())
5498 {
5499 m_type = value_t::array;
5500 m_value = value_t::array;
5501 assert_invariant();
5502 }
5503
5504 // add element to array
5505 const auto old_capacity = m_value.array->capacity();
5506 m_value.array->push_back(val);
5507 set_parent(m_value.array->back(), old_capacity);
5508 }
5509
5515 {
5516 push_back(val);
5517 return *this;
5518 }
5519
5540 void push_back(const typename object_t::value_type& val)
5541 {
5542 // push_back only works for null objects or objects
5543 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
5544 {
5545 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
5546 }
5547
5548 // transform null object into an object
5549 if (is_null())
5550 {
5551 m_type = value_t::object;
5552 m_value = value_t::object;
5553 assert_invariant();
5554 }
5555
5556 // add element to object
5557 auto res = m_value.object->insert(val);
5558 set_parent(res.first->second);
5559 }
5560
5565 reference operator+=(const typename object_t::value_type& val)
5566 {
5567 push_back(val);
5568 return *this;
5569 }
5570
5597 {
5598 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
5599 {
5600 basic_json&& key = init.begin()->moved_or_copied();
5601 push_back(typename object_t::value_type(
5602 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
5603 }
5604 else
5605 {
5606 push_back(basic_json(init));
5607 }
5608 }
5609
5615 {
5616 push_back(init);
5617 return *this;
5618 }
5619
5643 template<class... Args>
5644 reference emplace_back(Args&& ... args)
5645 {
5646 // emplace_back only works for null objects or arrays
5647 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
5648 {
5649 JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()), *this));
5650 }
5651
5652 // transform null object into an array
5653 if (is_null())
5654 {
5655 m_type = value_t::array;
5656 m_value = value_t::array;
5657 assert_invariant();
5658 }
5659
5660 // add element to array (perfect forwarding)
5661 const auto old_capacity = m_value.array->capacity();
5662 m_value.array->emplace_back(std::forward<Args>(args)...);
5663 return set_parent(m_value.array->back(), old_capacity);
5664 }
5665
5693 template<class... Args>
5694 std::pair<iterator, bool> emplace(Args&& ... args)
5695 {
5696 // emplace only works for null objects or arrays
5697 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
5698 {
5699 JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()), *this));
5700 }
5701
5702 // transform null object into an object
5703 if (is_null())
5704 {
5705 m_type = value_t::object;
5706 m_value = value_t::object;
5707 assert_invariant();
5708 }
5709
5710 // add element to array (perfect forwarding)
5711 auto res = m_value.object->emplace(std::forward<Args>(args)...);
5712 set_parent(res.first->second);
5713
5714 // create result iterator and set iterator to the result of emplace
5715 auto it = begin();
5716 it.m_it.object_iterator = res.first;
5717
5718 // return pair of iterator and boolean
5719 return {it, res.second};
5720 }
5721
5725 template<typename... Args>
5727 {
5728 iterator result(this);
5729 JSON_ASSERT(m_value.array != nullptr);
5730
5731 auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
5732 m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
5733 result.m_it.array_iterator = m_value.array->begin() + insert_pos;
5734
5735 // This could have been written as:
5736 // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5737 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
5738
5739 set_parents();
5740 return result;
5741 }
5742
5766 {
5767 // insert only works for arrays
5768 if (JSON_HEDLEY_LIKELY(is_array()))
5769 {
5770 // check if iterator pos fits to this JSON value
5771 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
5772 {
5773 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
5774 }
5775
5776 // insert to array and return iterator
5777 return insert_iterator(pos, val);
5778 }
5779
5780 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
5781 }
5782
5788 {
5789 return insert(pos, val);
5790 }
5791
5817 {
5818 // insert only works for arrays
5819 if (JSON_HEDLEY_LIKELY(is_array()))
5820 {
5821 // check if iterator pos fits to this JSON value
5822 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
5823 {
5824 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
5825 }
5826
5827 // insert to array and return iterator
5828 return insert_iterator(pos, cnt, val);
5829 }
5830
5831 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
5832 }
5833
5865 {
5866 // insert only works for arrays
5867 if (JSON_HEDLEY_UNLIKELY(!is_array()))
5868 {
5869 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
5870 }
5871
5872 // check if iterator pos fits to this JSON value
5873 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
5874 {
5875 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
5876 }
5877
5878 // check if range iterators belong to the same JSON object
5879 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
5880 {
5881 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
5882 }
5883
5884 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
5885 {
5886 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", *this));
5887 }
5888
5889 // insert to array and return iterator
5890 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
5891 }
5892
5918 {
5919 // insert only works for arrays
5920 if (JSON_HEDLEY_UNLIKELY(!is_array()))
5921 {
5922 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
5923 }
5924
5925 // check if iterator pos fits to this JSON value
5926 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
5927 {
5928 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
5929 }
5930
5931 // insert to array and return iterator
5932 return insert_iterator(pos, ilist.begin(), ilist.end());
5933 }
5934
5959 {
5960 // insert only works for objects
5961 if (JSON_HEDLEY_UNLIKELY(!is_object()))
5962 {
5963 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
5964 }
5965
5966 // check if range iterators belong to the same JSON object
5967 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
5968 {
5969 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
5970 }
5971
5972 // passed iterators must belong to objects
5973 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
5974 {
5975 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", *this));
5976 }
5977
5978 m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
5979 }
5980
6001 {
6002 // implicitly convert null value to an empty object
6003 if (is_null())
6004 {
6005 m_type = value_t::object;
6006 m_value.object = create<object_t>();
6007 assert_invariant();
6008 }
6009
6010 if (JSON_HEDLEY_UNLIKELY(!is_object()))
6011 {
6012 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), *this));
6013 }
6014 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
6015 {
6016 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name()), *this));
6017 }
6018
6019 for (auto it = j.cbegin(); it != j.cend(); ++it)
6020 {
6021 m_value.object->operator[](it.key()) = it.value();
6022#if JSON_DIAGNOSTICS
6023 m_value.object->operator[](it.key()).m_parent = this;
6024#endif
6025 }
6026 }
6027
6055 {
6056 // implicitly convert null value to an empty object
6057 if (is_null())
6058 {
6059 m_type = value_t::object;
6060 m_value.object = create<object_t>();
6061 assert_invariant();
6062 }
6063
6064 if (JSON_HEDLEY_UNLIKELY(!is_object()))
6065 {
6066 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), *this));
6067 }
6068
6069 // check if range iterators belong to the same JSON object
6070 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
6071 {
6072 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
6073 }
6074
6075 // passed iterators must belong to objects
6076 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()
6077 || !last.m_object->is_object()))
6078 {
6079 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", *this));
6080 }
6081
6082 for (auto it = first; it != last; ++it)
6083 {
6084 m_value.object->operator[](it.key()) = it.value();
6085#if JSON_DIAGNOSTICS
6086 m_value.object->operator[](it.key()).m_parent = this;
6087#endif
6088 }
6089 }
6090
6108 void swap(reference other) noexcept (
6109 std::is_nothrow_move_constructible<value_t>::value&&
6110 std::is_nothrow_move_assignable<value_t>::value&&
6111 std::is_nothrow_move_constructible<json_value>::value&&
6112 std::is_nothrow_move_assignable<json_value>::value
6113 )
6114 {
6115 std::swap(m_type, other.m_type);
6116 std::swap(m_value, other.m_value);
6117
6118 set_parents();
6119 other.set_parents();
6120 assert_invariant();
6121 }
6122
6141 friend void swap(reference left, reference right) noexcept (
6142 std::is_nothrow_move_constructible<value_t>::value&&
6143 std::is_nothrow_move_assignable<value_t>::value&&
6144 std::is_nothrow_move_constructible<json_value>::value&&
6145 std::is_nothrow_move_assignable<json_value>::value
6146 )
6147 {
6148 left.swap(right);
6149 }
6150
6171 void swap(array_t& other) // NOLINT(bugprone-exception-escape)
6172 {
6173 // swap only works for arrays
6174 if (JSON_HEDLEY_LIKELY(is_array()))
6175 {
6176 std::swap(*(m_value.array), other);
6177 }
6178 else
6179 {
6180 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
6181 }
6182 }
6183
6204 void swap(object_t& other) // NOLINT(bugprone-exception-escape)
6205 {
6206 // swap only works for objects
6207 if (JSON_HEDLEY_LIKELY(is_object()))
6208 {
6209 std::swap(*(m_value.object), other);
6210 }
6211 else
6212 {
6213 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
6214 }
6215 }
6216
6237 void swap(string_t& other) // NOLINT(bugprone-exception-escape)
6238 {
6239 // swap only works for strings
6240 if (JSON_HEDLEY_LIKELY(is_string()))
6241 {
6242 std::swap(*(m_value.string), other);
6243 }
6244 else
6245 {
6246 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
6247 }
6248 }
6249
6270 void swap(binary_t& other) // NOLINT(bugprone-exception-escape)
6271 {
6272 // swap only works for strings
6273 if (JSON_HEDLEY_LIKELY(is_binary()))
6274 {
6275 std::swap(*(m_value.binary), other);
6276 }
6277 else
6278 {
6279 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
6280 }
6281 }
6282
6284 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
6285 {
6286 // swap only works for strings
6287 if (JSON_HEDLEY_LIKELY(is_binary()))
6288 {
6289 std::swap(*(m_value.binary), other);
6290 }
6291 else
6292 {
6293 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
6294 }
6295 }
6296
6298
6299 public:
6301 // lexicographical comparison operators //
6303
6306
6362 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
6363 {
6364#ifdef __GNUC__
6365#pragma GCC diagnostic push
6366#pragma GCC diagnostic ignored "-Wfloat-equal"
6367#endif
6368 const auto lhs_type = lhs.type();
6369 const auto rhs_type = rhs.type();
6370
6371 if (lhs_type == rhs_type)
6372 {
6373 switch (lhs_type)
6374 {
6375 case value_t::array:
6376 return *lhs.m_value.array == *rhs.m_value.array;
6377
6378 case value_t::object:
6379 return *lhs.m_value.object == *rhs.m_value.object;
6380
6381 case value_t::null:
6382 return true;
6383
6384 case value_t::string:
6385 return *lhs.m_value.string == *rhs.m_value.string;
6386
6387 case value_t::boolean:
6388 return lhs.m_value.boolean == rhs.m_value.boolean;
6389
6390 case value_t::number_integer:
6391 return lhs.m_value.number_integer == rhs.m_value.number_integer;
6392
6393 case value_t::number_unsigned:
6394 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
6395
6396 case value_t::number_float:
6397 return lhs.m_value.number_float == rhs.m_value.number_float;
6398
6399 case value_t::binary:
6400 return *lhs.m_value.binary == *rhs.m_value.binary;
6401
6402 case value_t::discarded:
6403 default:
6404 return false;
6405 }
6406 }
6407 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)
6408 {
6409 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
6410 }
6411 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)
6412 {
6413 return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
6414 }
6415 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)
6416 {
6417 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
6418 }
6419 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)
6420 {
6421 return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
6422 }
6423 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)
6424 {
6425 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
6426 }
6427 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)
6428 {
6429 return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
6430 }
6431
6432 return false;
6433#ifdef __GNUC__
6434#pragma GCC diagnostic pop
6435#endif
6436 }
6437
6442 template<typename ScalarType, typename std::enable_if<
6443 std::is_scalar<ScalarType>::value, int>::type = 0>
6444 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
6445 {
6446 return lhs == basic_json(rhs);
6447 }
6448
6453 template<typename ScalarType, typename std::enable_if<
6454 std::is_scalar<ScalarType>::value, int>::type = 0>
6455 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
6456 {
6457 return basic_json(lhs) == rhs;
6458 }
6459
6478 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
6479 {
6480 return !(lhs == rhs);
6481 }
6482
6487 template<typename ScalarType, typename std::enable_if<
6488 std::is_scalar<ScalarType>::value, int>::type = 0>
6489 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
6490 {
6491 return lhs != basic_json(rhs);
6492 }
6493
6498 template<typename ScalarType, typename std::enable_if<
6499 std::is_scalar<ScalarType>::value, int>::type = 0>
6500 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
6501 {
6502 return basic_json(lhs) != rhs;
6503 }
6504
6531 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
6532 {
6533 const auto lhs_type = lhs.type();
6534 const auto rhs_type = rhs.type();
6535
6536 if (lhs_type == rhs_type)
6537 {
6538 switch (lhs_type)
6539 {
6540 case value_t::array:
6541 // note parentheses are necessary, see
6542 // https://github.com/nlohmann/json/issues/1530
6543 return (*lhs.m_value.array) < (*rhs.m_value.array);
6544
6545 case value_t::object:
6546 return (*lhs.m_value.object) < (*rhs.m_value.object);
6547
6548 case value_t::null:
6549 return false;
6550
6551 case value_t::string:
6552 return (*lhs.m_value.string) < (*rhs.m_value.string);
6553
6554 case value_t::boolean:
6555 return (lhs.m_value.boolean) < (rhs.m_value.boolean);
6556
6557 case value_t::number_integer:
6558 return (lhs.m_value.number_integer) < (rhs.m_value.number_integer);
6559
6560 case value_t::number_unsigned:
6561 return (lhs.m_value.number_unsigned) < (rhs.m_value.number_unsigned);
6562
6563 case value_t::number_float:
6564 return (lhs.m_value.number_float) < (rhs.m_value.number_float);
6565
6566 case value_t::binary:
6567 return (*lhs.m_value.binary) < (*rhs.m_value.binary);
6568
6569 case value_t::discarded:
6570 default:
6571 return false;
6572 }
6573 }
6574 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)
6575 {
6576 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
6577 }
6578 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)
6579 {
6580 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
6581 }
6582 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)
6583 {
6584 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
6585 }
6586 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)
6587 {
6588 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
6589 }
6590 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)
6591 {
6592 return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
6593 }
6594 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)
6595 {
6596 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
6597 }
6598
6599 // We only reach this line if we cannot compare values. In that case,
6600 // we compare types. Note we have to call the operator explicitly,
6601 // because MSVC has problems otherwise.
6602 return operator<(lhs_type, rhs_type);
6603 }
6604
6609 template<typename ScalarType, typename std::enable_if<
6610 std::is_scalar<ScalarType>::value, int>::type = 0>
6611 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
6612 {
6613 return lhs < basic_json(rhs);
6614 }
6615
6620 template<typename ScalarType, typename std::enable_if<
6621 std::is_scalar<ScalarType>::value, int>::type = 0>
6622 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
6623 {
6624 return basic_json(lhs) < rhs;
6625 }
6626
6646 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
6647 {
6648 return !(rhs < lhs);
6649 }
6650
6655 template<typename ScalarType, typename std::enable_if<
6656 std::is_scalar<ScalarType>::value, int>::type = 0>
6657 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
6658 {
6659 return lhs <= basic_json(rhs);
6660 }
6661
6666 template<typename ScalarType, typename std::enable_if<
6667 std::is_scalar<ScalarType>::value, int>::type = 0>
6668 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
6669 {
6670 return basic_json(lhs) <= rhs;
6671 }
6672
6692 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
6693 {
6694 return !(lhs <= rhs);
6695 }
6696
6701 template<typename ScalarType, typename std::enable_if<
6702 std::is_scalar<ScalarType>::value, int>::type = 0>
6703 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
6704 {
6705 return lhs > basic_json(rhs);
6706 }
6707
6712 template<typename ScalarType, typename std::enable_if<
6713 std::is_scalar<ScalarType>::value, int>::type = 0>
6714 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
6715 {
6716 return basic_json(lhs) > rhs;
6717 }
6718
6738 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
6739 {
6740 return !(lhs < rhs);
6741 }
6742
6747 template<typename ScalarType, typename std::enable_if<
6748 std::is_scalar<ScalarType>::value, int>::type = 0>
6749 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
6750 {
6751 return lhs >= basic_json(rhs);
6752 }
6753
6758 template<typename ScalarType, typename std::enable_if<
6759 std::is_scalar<ScalarType>::value, int>::type = 0>
6760 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
6761 {
6762 return basic_json(lhs) >= rhs;
6763 }
6764
6766
6768 // serialization //
6770
6773#ifndef JSON_NO_IO
6805 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
6806 {
6807 // read width member and use it as indentation parameter if nonzero
6808 const bool pretty_print = o.width() > 0;
6809 const auto indentation = pretty_print ? o.width() : 0;
6810
6811 // reset width to 0 for subsequent calls to this stream
6812 o.width(0);
6813
6814 // do the actual serialization
6815 serializer s(detail::output_adapter<char>(o), o.fill());
6816 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
6817 return o;
6818 }
6819
6828 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
6829 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
6830 {
6831 return o << j;
6832 }
6833#endif // JSON_NO_IO
6835
6836
6838 // deserialization //
6840
6843
6895 template<typename InputType>
6896 JSON_HEDLEY_WARN_UNUSED_RESULT
6897 static basic_json parse(InputType&& i,
6898 const parser_callback_t cb = nullptr,
6899 const bool allow_exceptions = true,
6900 const bool ignore_comments = false)
6901 {
6902 basic_json result;
6903 parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
6904 return result;
6905 }
6906
6933 template<typename IteratorType>
6934 JSON_HEDLEY_WARN_UNUSED_RESULT
6935 static basic_json parse(IteratorType first,
6936 IteratorType last,
6937 const parser_callback_t cb = nullptr,
6938 const bool allow_exceptions = true,
6939 const bool ignore_comments = false)
6940 {
6941 basic_json result;
6942 parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
6943 return result;
6944 }
6945
6946 JSON_HEDLEY_WARN_UNUSED_RESULT
6947 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
6949 const parser_callback_t cb = nullptr,
6950 const bool allow_exceptions = true,
6951 const bool ignore_comments = false)
6952 {
6953 basic_json result;
6954 parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
6955 return result;
6956 }
6957
6988 template<typename InputType>
6989 static bool accept(InputType&& i,
6990 const bool ignore_comments = false)
6991 {
6992 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
6993 }
6994
6995 template<typename IteratorType>
6996 static bool accept(IteratorType first, IteratorType last,
6997 const bool ignore_comments = false)
6998 {
6999 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
7000 }
7001
7002 JSON_HEDLEY_WARN_UNUSED_RESULT
7003 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
7004 static bool accept(detail::span_input_adapter&& i,
7005 const bool ignore_comments = false)
7006 {
7007 return parser(i.get(), nullptr, false, ignore_comments).accept(true);
7008 }
7009
7050 template <typename InputType, typename SAX>
7051 JSON_HEDLEY_NON_NULL(2)
7052 static bool sax_parse(InputType&& i, SAX* sax,
7054 const bool strict = true,
7055 const bool ignore_comments = false)
7056 {
7057 auto ia = detail::input_adapter(std::forward<InputType>(i));
7058 return format == input_format_t::json
7059 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
7060 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
7061 }
7062
7063 template<class IteratorType, class SAX>
7064 JSON_HEDLEY_NON_NULL(3)
7065 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
7066 input_format_t format = input_format_t::json,
7067 const bool strict = true,
7068 const bool ignore_comments = false)
7069 {
7070 auto ia = detail::input_adapter(std::move(first), std::move(last));
7071 return format == input_format_t::json
7072 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
7073 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
7074 }
7075
7076 template <typename SAX>
7077 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
7078 JSON_HEDLEY_NON_NULL(2)
7079 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
7080 input_format_t format = input_format_t::json,
7081 const bool strict = true,
7082 const bool ignore_comments = false)
7083 {
7084 auto ia = i.get();
7085 return format == input_format_t::json
7086 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
7087 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
7088 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
7089 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
7090 }
7091#ifndef JSON_NO_IO
7100 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
7101 friend std::istream& operator<<(basic_json& j, std::istream& i)
7102 {
7103 return operator>>(i, j);
7104 }
7105
7131 friend std::istream& operator>>(std::istream& i, basic_json& j)
7132 {
7133 parser(detail::input_adapter(i)).parse(false, j);
7134 return i;
7135 }
7136#endif // JSON_NO_IO
7138
7140 // convenience functions //
7142
7174 JSON_HEDLEY_RETURNS_NON_NULL
7175 const char* type_name() const noexcept
7176 {
7177 {
7178 switch (m_type)
7179 {
7180 case value_t::null:
7181 return "null";
7182 case value_t::object:
7183 return "object";
7184 case value_t::array:
7185 return "array";
7186 case value_t::string:
7187 return "string";
7188 case value_t::boolean:
7189 return "boolean";
7190 case value_t::binary:
7191 return "binary";
7192 case value_t::discarded:
7193 return "discarded";
7194 case value_t::number_integer:
7195 case value_t::number_unsigned:
7196 case value_t::number_float:
7197 default:
7198 return "number";
7199 }
7200 }
7201 }
7202
7203
7204 JSON_PRIVATE_UNLESS_TESTED:
7206 // member variables //
7208
7210 value_t m_type = value_t::null;
7211
7213 json_value m_value = {};
7214
7215#if JSON_DIAGNOSTICS
7217 basic_json* m_parent = nullptr;
7218#endif
7219
7221 // binary serialization/deserialization //
7223
7226
7227 public:
7326 static std::vector<std::uint8_t> to_cbor(const basic_json& j)
7327 {
7328 std::vector<std::uint8_t> result;
7329 to_cbor(j, result);
7330 return result;
7331 }
7332
7334 {
7335 binary_writer<std::uint8_t>(o).write_cbor(j);
7336 }
7337
7338 static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
7339 {
7340 binary_writer<char>(o).write_cbor(j);
7341 }
7342
7421 static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
7422 {
7423 std::vector<std::uint8_t> result;
7424 to_msgpack(j, result);
7425 return result;
7426 }
7427
7429 {
7430 binary_writer<std::uint8_t>(o).write_msgpack(j);
7431 }
7432
7433 static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
7434 {
7435 binary_writer<char>(o).write_msgpack(j);
7436 }
7437
7524 static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
7525 const bool use_size = false,
7526 const bool use_type = false)
7527 {
7528 std::vector<std::uint8_t> result;
7529 to_ubjson(j, result, use_size, use_type);
7530 return result;
7531 }
7532
7534 const bool use_size = false, const bool use_type = false)
7535 {
7536 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
7537 }
7538
7539 static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
7540 const bool use_size = false, const bool use_type = false)
7541 {
7542 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
7543 }
7544
7545
7602 static std::vector<std::uint8_t> to_bson(const basic_json& j)
7603 {
7604 std::vector<std::uint8_t> result;
7605 to_bson(j, result);
7606 return result;
7607 }
7608
7621
7626 {
7628 }
7629
7630
7733 template<typename InputType>
7734 JSON_HEDLEY_WARN_UNUSED_RESULT
7735 static basic_json from_cbor(InputType&& i,
7736 const bool strict = true,
7737 const bool allow_exceptions = true,
7738 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
7739 {
7740 basic_json result;
7741 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
7742 auto ia = detail::input_adapter(std::forward<InputType>(i));
7743 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
7744 return res ? result : basic_json(value_t::discarded);
7745 }
7746
7750 template<typename IteratorType>
7751 JSON_HEDLEY_WARN_UNUSED_RESULT
7752 static basic_json from_cbor(IteratorType first, IteratorType last,
7753 const bool strict = true,
7754 const bool allow_exceptions = true,
7755 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
7756 {
7757 basic_json result;
7758 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
7759 auto ia = detail::input_adapter(std::move(first), std::move(last));
7760 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
7761 return res ? result : basic_json(value_t::discarded);
7762 }
7763
7764 template<typename T>
7765 JSON_HEDLEY_WARN_UNUSED_RESULT
7766 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
7767 static basic_json from_cbor(const T* ptr, std::size_t len,
7768 const bool strict = true,
7769 const bool allow_exceptions = true,
7770 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
7771 {
7772 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
7773 }
7774
7775
7776 JSON_HEDLEY_WARN_UNUSED_RESULT
7777 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
7778 static basic_json from_cbor(detail::span_input_adapter&& i,
7779 const bool strict = true,
7780 const bool allow_exceptions = true,
7781 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
7782 {
7783 basic_json result;
7784 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
7785 auto ia = i.get();
7786 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
7787 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
7788 return res ? result : basic_json(value_t::discarded);
7789 }
7790
7877 template<typename InputType>
7878 JSON_HEDLEY_WARN_UNUSED_RESULT
7879 static basic_json from_msgpack(InputType&& i,
7880 const bool strict = true,
7881 const bool allow_exceptions = true)
7882 {
7883 basic_json result;
7884 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
7885 auto ia = detail::input_adapter(std::forward<InputType>(i));
7886 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
7887 return res ? result : basic_json(value_t::discarded);
7888 }
7889
7893 template<typename IteratorType>
7894 JSON_HEDLEY_WARN_UNUSED_RESULT
7895 static basic_json from_msgpack(IteratorType first, IteratorType last,
7896 const bool strict = true,
7897 const bool allow_exceptions = true)
7898 {
7899 basic_json result;
7900 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
7901 auto ia = detail::input_adapter(std::move(first), std::move(last));
7902 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
7903 return res ? result : basic_json(value_t::discarded);
7904 }
7905
7906
7907 template<typename T>
7908 JSON_HEDLEY_WARN_UNUSED_RESULT
7909 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
7910 static basic_json from_msgpack(const T* ptr, std::size_t len,
7911 const bool strict = true,
7912 const bool allow_exceptions = true)
7913 {
7914 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
7915 }
7916
7917 JSON_HEDLEY_WARN_UNUSED_RESULT
7918 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
7919 static basic_json from_msgpack(detail::span_input_adapter&& i,
7920 const bool strict = true,
7921 const bool allow_exceptions = true)
7922 {
7923 basic_json result;
7924 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
7925 auto ia = i.get();
7926 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
7927 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
7928 return res ? result : basic_json(value_t::discarded);
7929 }
7930
7931
7994 template<typename InputType>
7995 JSON_HEDLEY_WARN_UNUSED_RESULT
7996 static basic_json from_ubjson(InputType&& i,
7997 const bool strict = true,
7998 const bool allow_exceptions = true)
7999 {
8000 basic_json result;
8001 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
8002 auto ia = detail::input_adapter(std::forward<InputType>(i));
8003 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
8004 return res ? result : basic_json(value_t::discarded);
8005 }
8006
8010 template<typename IteratorType>
8011 JSON_HEDLEY_WARN_UNUSED_RESULT
8012 static basic_json from_ubjson(IteratorType first, IteratorType last,
8013 const bool strict = true,
8014 const bool allow_exceptions = true)
8015 {
8016 basic_json result;
8017 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
8018 auto ia = detail::input_adapter(std::move(first), std::move(last));
8019 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
8020 return res ? result : basic_json(value_t::discarded);
8021 }
8022
8023 template<typename T>
8024 JSON_HEDLEY_WARN_UNUSED_RESULT
8025 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
8026 static basic_json from_ubjson(const T* ptr, std::size_t len,
8027 const bool strict = true,
8028 const bool allow_exceptions = true)
8029 {
8030 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
8031 }
8032
8033 JSON_HEDLEY_WARN_UNUSED_RESULT
8034 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
8035 static basic_json from_ubjson(detail::span_input_adapter&& i,
8036 const bool strict = true,
8037 const bool allow_exceptions = true)
8038 {
8039 basic_json result;
8040 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
8041 auto ia = i.get();
8042 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
8043 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
8044 return res ? result : basic_json(value_t::discarded);
8045 }
8046
8047
8108 template<typename InputType>
8109 JSON_HEDLEY_WARN_UNUSED_RESULT
8110 static basic_json from_bson(InputType&& i,
8111 const bool strict = true,
8112 const bool allow_exceptions = true)
8113 {
8114 basic_json result;
8115 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
8116 auto ia = detail::input_adapter(std::forward<InputType>(i));
8117 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
8118 return res ? result : basic_json(value_t::discarded);
8119 }
8120
8124 template<typename IteratorType>
8125 JSON_HEDLEY_WARN_UNUSED_RESULT
8126 static basic_json from_bson(IteratorType first, IteratorType last,
8127 const bool strict = true,
8128 const bool allow_exceptions = true)
8129 {
8130 basic_json result;
8131 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
8132 auto ia = detail::input_adapter(std::move(first), std::move(last));
8133 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
8134 return res ? result : basic_json(value_t::discarded);
8135 }
8136
8137 template<typename T>
8138 JSON_HEDLEY_WARN_UNUSED_RESULT
8139 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
8140 static basic_json from_bson(const T* ptr, std::size_t len,
8141 const bool strict = true,
8142 const bool allow_exceptions = true)
8143 {
8144 return from_bson(ptr, ptr + len, strict, allow_exceptions);
8145 }
8146
8147 JSON_HEDLEY_WARN_UNUSED_RESULT
8148 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
8149 static basic_json from_bson(detail::span_input_adapter&& i,
8150 const bool strict = true,
8151 const bool allow_exceptions = true)
8152 {
8153 basic_json result;
8154 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
8155 auto ia = i.get();
8156 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
8157 const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
8158 return res ? result : basic_json(value_t::discarded);
8159 }
8161
8163 // JSON Pointer support //
8165
8168
8203 {
8204 return ptr.get_unchecked(this);
8205 }
8206
8231 {
8232 return ptr.get_unchecked(this);
8233 }
8234
8274 {
8275 return ptr.get_checked(this);
8276 }
8277
8317 {
8318 return ptr.get_checked(this);
8319 }
8320
8344 {
8345 basic_json result(value_t::object);
8346 json_pointer::flatten("", *this, result);
8347 return result;
8348 }
8349
8381 {
8382 return json_pointer::unflatten(*this);
8383 }
8384
8386
8388 // JSON Patch functions //
8390
8393
8441 basic_json patch(const basic_json& json_patch) const
8442 {
8443 // make a working copy to apply the patch to
8444 basic_json result = *this;
8445
8446 // the valid JSON Patch operations
8447 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
8448
8449 const auto get_op = [](const std::string & op)
8450 {
8451 if (op == "add")
8452 {
8453 return patch_operations::add;
8454 }
8455 if (op == "remove")
8456 {
8457 return patch_operations::remove;
8458 }
8459 if (op == "replace")
8460 {
8461 return patch_operations::replace;
8462 }
8463 if (op == "move")
8464 {
8465 return patch_operations::move;
8466 }
8467 if (op == "copy")
8468 {
8469 return patch_operations::copy;
8470 }
8471 if (op == "test")
8472 {
8473 return patch_operations::test;
8474 }
8475
8476 return patch_operations::invalid;
8477 };
8478
8479 // wrapper for "add" operation; add value at ptr
8480 const auto operation_add = [&result](json_pointer & ptr, basic_json val)
8481 {
8482 // adding to the root of the target document means replacing it
8483 if (ptr.empty())
8484 {
8485 result = val;
8486 return;
8487 }
8488
8489 // make sure the top element of the pointer exists
8490 json_pointer top_pointer = ptr.top();
8491 if (top_pointer != ptr)
8492 {
8493 result.at(top_pointer);
8494 }
8495
8496 // get reference to parent of JSON pointer ptr
8497 const auto last_path = ptr.back();
8498 ptr.pop_back();
8499 basic_json& parent = result[ptr];
8500
8501 switch (parent.m_type)
8502 {
8503 case value_t::null:
8504 case value_t::object:
8505 {
8506 // use operator[] to add value
8507 parent[last_path] = val;
8508 break;
8509 }
8510
8511 case value_t::array:
8512 {
8513 if (last_path == "-")
8514 {
8515 // special case: append to back
8516 parent.push_back(val);
8517 }
8518 else
8519 {
8520 const auto idx = json_pointer::array_index(last_path);
8521 if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
8522 {
8523 // avoid undefined behavior
8524 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", parent));
8525 }
8526
8527 // default case: insert add offset
8528 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
8529 }
8530 break;
8531 }
8532
8533 // if there exists a parent it cannot be primitive
8534 case value_t::string: // LCOV_EXCL_LINE
8535 case value_t::boolean: // LCOV_EXCL_LINE
8536 case value_t::number_integer: // LCOV_EXCL_LINE
8537 case value_t::number_unsigned: // LCOV_EXCL_LINE
8538 case value_t::number_float: // LCOV_EXCL_LINE
8539 case value_t::binary: // LCOV_EXCL_LINE
8540 case value_t::discarded: // LCOV_EXCL_LINE
8541 default: // LCOV_EXCL_LINE
8542 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8543 }
8544 };
8545
8546 // wrapper for "remove" operation; remove value at ptr
8547 const auto operation_remove = [this, &result](json_pointer & ptr)
8548 {
8549 // get reference to parent of JSON pointer ptr
8550 const auto last_path = ptr.back();
8551 ptr.pop_back();
8552 basic_json& parent = result.at(ptr);
8553
8554 // remove child
8555 if (parent.is_object())
8556 {
8557 // perform range check
8558 auto it = parent.find(last_path);
8559 if (JSON_HEDLEY_LIKELY(it != parent.end()))
8560 {
8561 parent.erase(it);
8562 }
8563 else
8564 {
8565 JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found", *this));
8566 }
8567 }
8568 else if (parent.is_array())
8569 {
8570 // note erase performs range check
8571 parent.erase(json_pointer::array_index(last_path));
8572 }
8573 };
8574
8575 // type check: top level value must be an array
8576 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
8577 {
8578 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", json_patch));
8579 }
8580
8581 // iterate and apply the operations
8582 for (const auto& val : json_patch)
8583 {
8584 // wrapper to get a value for an operation
8585 const auto get_value = [&val](const std::string & op,
8586 const std::string & member,
8587 bool string_type) -> basic_json &
8588 {
8589 // find value
8590 auto it = val.m_value.object->find(member);
8591
8592 // context-sensitive error message
8593 const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
8594
8595 // check if desired value is present
8596 if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end()))
8597 {
8598 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
8599 JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'", val));
8600 }
8601
8602 // check if result is of type string
8603 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
8604 {
8605 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
8606 JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'", val));
8607 }
8608
8609 // no error: return value
8610 return it->second;
8611 };
8612
8613 // type check: every element of the array must be an object
8614 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
8615 {
8616 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", val));
8617 }
8618
8619 // collect mandatory members
8620 const auto op = get_value("op", "op", true).template get<std::string>();
8621 const auto path = get_value(op, "path", true).template get<std::string>();
8622 json_pointer ptr(path);
8623
8624 switch (get_op(op))
8625 {
8626 case patch_operations::add:
8627 {
8628 operation_add(ptr, get_value("add", "value", false));
8629 break;
8630 }
8631
8632 case patch_operations::remove:
8633 {
8634 operation_remove(ptr);
8635 break;
8636 }
8637
8638 case patch_operations::replace:
8639 {
8640 // the "path" location must exist - use at()
8641 result.at(ptr) = get_value("replace", "value", false);
8642 break;
8643 }
8644
8645 case patch_operations::move:
8646 {
8647 const auto from_path = get_value("move", "from", true).template get<std::string>();
8648 json_pointer from_ptr(from_path);
8649
8650 // the "from" location must exist - use at()
8651 basic_json v = result.at(from_ptr);
8652
8653 // The move operation is functionally identical to a
8654 // "remove" operation on the "from" location, followed
8655 // immediately by an "add" operation at the target
8656 // location with the value that was just removed.
8657 operation_remove(from_ptr);
8658 operation_add(ptr, v);
8659 break;
8660 }
8661
8662 case patch_operations::copy:
8663 {
8664 const auto from_path = get_value("copy", "from", true).template get<std::string>();
8665 const json_pointer from_ptr(from_path);
8666
8667 // the "from" location must exist - use at()
8668 basic_json v = result.at(from_ptr);
8669
8670 // The copy is functionally identical to an "add"
8671 // operation at the target location using the value
8672 // specified in the "from" member.
8673 operation_add(ptr, v);
8674 break;
8675 }
8676
8677 case patch_operations::test:
8678 {
8679 bool success = false;
8680 JSON_TRY
8681 {
8682 // check if "value" matches the one at "path"
8683 // the "path" location must exist - use at()
8684 success = (result.at(ptr) == get_value("test", "value", false));
8685 }
8686 JSON_INTERNAL_CATCH (out_of_range&)
8687 {
8688 // ignore out of range errors: success remains false
8689 }
8690
8691 // throw an exception if test fails
8692 if (JSON_HEDLEY_UNLIKELY(!success))
8693 {
8694 JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump(), val));
8695 }
8696
8697 break;
8698 }
8699
8700 case patch_operations::invalid:
8701 default:
8702 {
8703 // op must be "add", "remove", "replace", "move", "copy", or
8704 // "test"
8705 JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid", val));
8706 }
8707 }
8708 }
8709
8710 return result;
8711 }
8712
8746 JSON_HEDLEY_WARN_UNUSED_RESULT
8747 static basic_json diff(const basic_json& source, const basic_json& target,
8748 const std::string& path = "")
8749 {
8750 // the patch
8751 basic_json result(value_t::array);
8752
8753 // if the values are the same, return empty patch
8754 if (source == target)
8755 {
8756 return result;
8757 }
8758
8759 if (source.type() != target.type())
8760 {
8761 // different types: replace value
8762 result.push_back(
8763 {
8764 {"op", "replace"}, {"path", path}, {"value", target}
8765 });
8766 return result;
8767 }
8768
8769 switch (source.type())
8770 {
8771 case value_t::array:
8772 {
8773 // first pass: traverse common elements
8774 std::size_t i = 0;
8775 while (i < source.size() && i < target.size())
8776 {
8777 // recursive call to compare array values at index i
8778 auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
8779 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
8780 ++i;
8781 }
8782
8783 // i now reached the end of at least one array
8784 // in a second pass, traverse the remaining elements
8785
8786 // remove my remaining elements
8787 const auto end_index = static_cast<difference_type>(result.size());
8788 while (i < source.size())
8789 {
8790 // add operations in reverse order to avoid invalid
8791 // indices
8792 result.insert(result.begin() + end_index, object(
8793 {
8794 {"op", "remove"},
8795 {"path", path + "/" + std::to_string(i)}
8796 }));
8797 ++i;
8798 }
8799
8800 // add other remaining elements
8801 while (i < target.size())
8802 {
8803 result.push_back(
8804 {
8805 {"op", "add"},
8806 {"path", path + "/-"},
8807 {"value", target[i]}
8808 });
8809 ++i;
8810 }
8811
8812 break;
8813 }
8814
8815 case value_t::object:
8816 {
8817 // first pass: traverse this object's elements
8818 for (auto it = source.cbegin(); it != source.cend(); ++it)
8819 {
8820 // escape the key name to be used in a JSON patch
8821 const auto path_key = path + "/" + detail::escape(it.key());
8822
8823 if (target.find(it.key()) != target.end())
8824 {
8825 // recursive call to compare object values at key it
8826 auto temp_diff = diff(it.value(), target[it.key()], path_key);
8827 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
8828 }
8829 else
8830 {
8831 // found a key that is not in o -> remove it
8832 result.push_back(object(
8833 {
8834 {"op", "remove"}, {"path", path_key}
8835 }));
8836 }
8837 }
8838
8839 // second pass: traverse other object's elements
8840 for (auto it = target.cbegin(); it != target.cend(); ++it)
8841 {
8842 if (source.find(it.key()) == source.end())
8843 {
8844 // found a key that is not in this -> add it
8845 const auto path_key = path + "/" + detail::escape(it.key());
8846 result.push_back(
8847 {
8848 {"op", "add"}, {"path", path_key},
8849 {"value", it.value()}
8850 });
8851 }
8852 }
8853
8854 break;
8855 }
8856
8857 case value_t::null:
8858 case value_t::string:
8859 case value_t::boolean:
8860 case value_t::number_integer:
8861 case value_t::number_unsigned:
8862 case value_t::number_float:
8863 case value_t::binary:
8864 case value_t::discarded:
8865 default:
8866 {
8867 // both primitive type: replace value
8868 result.push_back(
8869 {
8870 {"op", "replace"}, {"path", path}, {"value", target}
8871 });
8872 break;
8873 }
8874 }
8875
8876 return result;
8877 }
8878
8880
8882 // JSON Merge Patch functions //
8884
8887
8930 void merge_patch(const basic_json& apply_patch)
8931 {
8932 if (apply_patch.is_object())
8933 {
8934 if (!is_object())
8935 {
8936 *this = object();
8937 }
8938 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
8939 {
8940 if (it.value().is_null())
8941 {
8942 erase(it.key());
8943 }
8944 else
8945 {
8946 operator[](it.key()).merge_patch(it.value());
8947 }
8948 }
8949 }
8950 else
8951 {
8952 *this = apply_patch;
8953 }
8954 }
8955
8957};
8958
8968NLOHMANN_BASIC_JSON_TPL_DECLARATION
8969std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
8970{
8971 return j.dump();
8972}
8973} // namespace nlohmann
8974
8976// nonmember support //
8978
8979// specialization of std::swap, and std::hash
8980namespace std
8981{
8982
8984template<>
8985struct hash<nlohmann::json>
8986{
8992 std::size_t operator()(const nlohmann::json& j) const
8993 {
8994 return nlohmann::detail::hash(j);
8995 }
8996};
8997
9001template<>
9003{
9009 nlohmann::detail::value_t rhs) const noexcept
9010 {
9011 return nlohmann::detail::operator<(lhs, rhs);
9012 }
9013};
9014
9015// C++20 prohibit function specialization in the std namespace.
9016#ifndef JSON_HAS_CPP_20
9017
9023template<>
9024inline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name)
9025 is_nothrow_move_constructible<nlohmann::json>::value&& // NOLINT(misc-redundant-expression)
9026 is_nothrow_move_assignable<nlohmann::json>::value
9027 )
9028{
9029 j1.swap(j2);
9030}
9031
9032#endif
9033
9034} // namespace std
9035
9049JSON_HEDLEY_NON_NULL(1)
9050inline nlohmann::json operator "" _json(const char* s, std::size_t n)
9051{
9052 return nlohmann::json::parse(s, s + n);
9053}
9054
9068JSON_HEDLEY_NON_NULL(1)
9069inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
9070{
9071 return nlohmann::json::json_pointer(std::string(s, n));
9072}
9073
9074#include <nlohmann/detail/macro_unscope.hpp>
9075
9076#endif // INCLUDE_NLOHMANN_JSON_HPP_
a class to store JSON values
Definition json.hpp:177
void insert(const_iterator first, const_iterator last)
inserts elements
Definition json.hpp:5958
detail::parser_callback_t< basic_json > parser_callback_t
per-element parser callback type
Definition json.hpp:1433
bool contains(KeyT &&key) const
check the existence of an element in a JSON object
Definition json.hpp:4610
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:5070
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition json.hpp:4895
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:8230
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:8202
friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
comparison: equal
Definition json.hpp:6444
ValueType value(const typename object_t::key_type &key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:3989
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition json.hpp:2688
NumberIntegerType number_integer_t
a type for a number (integer)
Definition json.hpp:711
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition json.hpp:6362
static bool sax_parse(InputType &&i, SAX *sax, input_format_t format=input_format_t::json, const bool strict=true, const bool ignore_comments=false)
generate SAX events
Definition json.hpp:7052
ReferenceType get_ref()
get a reference value (implicit)
Definition json.hpp:3352
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json parse(InputType &&i, const parser_callback_t cb=nullptr, const bool allow_exceptions=true, const bool ignore_comments=false)
deserialize from a compatible input
Definition json.hpp:6897
reference emplace_back(Args &&... args)
add an object to an array
Definition json.hpp:5644
const_iterator find(KeyT &&key) const
find an element in a JSON object
Definition json.hpp:4543
basic_json(const value_t v)
create an empty value with a given type
Definition json.hpp:1474
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition json.hpp:5293
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json diff(const basic_json &source, const basic_json &target, const std::string &path="")
creates a diff as a JSON patch
Definition json.hpp:8747
static std::vector< std::uint8_t > to_bson(const basic_json &j)
Serializes the given JSON object j to BSON and returns a vector containing the corresponding BSON-rep...
Definition json.hpp:7602
value_type & reference
the type of an element reference
Definition json.hpp:290
void erase(const size_type idx)
remove element from a JSON array given an index
Definition json.hpp:4473
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition json.hpp:4924
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition json.hpp:3635
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition json.hpp:3584
iterator begin() noexcept
returns an iterator to the first element
Definition json.hpp:4680
binary_t & get_binary()
Definition json.hpp:3428
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition json.hpp:2053
static std::vector< std::uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition json.hpp:7421
friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
comparison: equal
Definition json.hpp:6455
static std::vector< std::uint8_t > to_cbor(const basic_json &j)
create a CBOR serialization of a given JSON value
Definition json.hpp:7326
basic_json & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&std::is_nothrow_move_assignable< json_value >::value)
copy assignment
Definition json.hpp:2320
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json array(initializer_list_t init={})
explicitly create an array from an initializer list
Definition json.hpp:1916
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition json.hpp:4866
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition json.hpp:4791
reference back()
access the last element
Definition json.hpp:4159
const binary_t & get_binary() const
Definition json.hpp:3439
static bool accept(InputType &&i, const bool ignore_comments=false)
check if the input is valid JSON
Definition json.hpp:6989
StringType string_t
a type for a string
Definition json.hpp:613
size_type size() const noexcept
returns the number of elements
Definition json.hpp:5215
void push_back(const basic_json &val)
add an object to an array
Definition json.hpp:5488
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json meta()
returns version information on the library
Definition json.hpp:354
ValueType value(const json_pointer &ptr, const ValueType &default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:4061
void update(const_reference j)
updates a JSON object from another object, overwriting existing keys
Definition json.hpp:6000
std::size_t size_type
a type to represent container sizes
Definition json.hpp:297
ValueType & get_to(ValueType &v) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), v)))
get a value (explicit)
Definition json.hpp:3292
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition json.hpp:295
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init)
explicitly create a binary array (without subtype)
Definition json.hpp:1813
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition json.hpp:3782
reference operator+=(basic_json &&val)
add an object to an array
Definition json.hpp:5478
basic_json(const BasicJsonType &val)
create a JSON value from an existing one
Definition json.hpp:1608
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition json.hpp:305
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
Create a JSON value from an input in BSON format.
Definition json.hpp:8126
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition json.hpp:303
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(InputType &&i, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
Definition json.hpp:7735
BooleanType boolean_t
a type for a boolean
Definition json.hpp:639
void push_back(initializer_list_t init)
add an object to an object
Definition json.hpp:5596
string_t dump(const int indent=-1, const char indent_char=' ', const bool ensure_ascii=false, const error_handler_t error_handler=error_handler_t::strict) const
serialization
Definition json.hpp:2418
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition json.hpp:4226
static void to_bson(const basic_json &j, detail::output_adapter< std::uint8_t > o)
Serializes the given JSON object j to BSON and forwards the corresponding BSON-representation to the ...
Definition json.hpp:7617
friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
comparison: not equal
Definition json.hpp:6489
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
Create a JSON value from an input in BSON format.
Definition json.hpp:8110
constexpr bool is_structured() const noexcept
return whether type is structured
Definition json.hpp:2529
friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition json.hpp:6668
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition json.hpp:4690
friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
comparison: less than
Definition json.hpp:6611
reference at(size_type idx)
access specified array element with bounds checking
Definition json.hpp:3486
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init, typename binary_t::subtype_type subtype)
binary (stored with pointer to save storage)
Definition json.hpp:1870
reference front()
access the first element
Definition json.hpp:4115
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition json.hpp:2502
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition json.hpp:2660
detail::cbor_tag_handler_t cbor_tag_handler_t
how to treat CBOR tags
Definition json.hpp:245
void swap(object_t &other)
exchanges the values
Definition json.hpp:6204
constexpr bool is_object() const noexcept
return whether value is an object
Definition json.hpp:2710
const_reference front() const
access the first element
Definition json.hpp:4123
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition json.hpp:2471
NumberFloatType number_float_t
a type for a number (floating-point)
Definition json.hpp:850
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
Definition json.hpp:312
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition json.hpp:6805
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition json.hpp:6646
bool empty() const noexcept
checks whether the container is empty.
Definition json.hpp:5135
basic_json(const basic_json &other)
copy constructor
Definition json.hpp:2190
~basic_json() noexcept
destructor
Definition json.hpp:2354
static std::vector< std::uint8_t > to_ubjson(const basic_json &j, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.hpp:7524
basic_json(basic_json &&other) noexcept
move constructor
Definition json.hpp:2282
friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
comparison: greater than
Definition json.hpp:6714
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition json.hpp:6478
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition json.hpp:5816
friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
comparison: less than
Definition json.hpp:6622
json_value m_value
the value of the current element
Definition json.hpp:7213
void swap(typename binary_t::container_type &other)
exchanges the values
Definition json.hpp:6284
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition json.hpp:6738
void swap(array_t &other)
exchanges the values
Definition json.hpp:6171
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition json.hpp:4858
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
Definition json.hpp:1850
static iteration_proxy< iterator > iterator_wrapper(reference ref) noexcept
wrapper to access iterator member functions in range-based for
Definition json.hpp:4988
ReferenceType get_ref() const
get a reference value (implicit)
Definition json.hpp:3365
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition json.hpp:5864
auto get() noexcept -> decltype(std::declval< basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition json.hpp:3248
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:8316
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition json.hpp:4761
void merge_patch(const basic_json &apply_patch)
applies a JSON Merge Patch
Definition json.hpp:8930
auto get_ptr() noexcept -> decltype(std::declval< basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.hpp:3006
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:5078
iterator insert(const_iterator pos, initializer_list_t ilist)
inserts elements
Definition json.hpp:5917
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
Definition json.hpp:560
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition json.hpp:6692
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition json.hpp:4341
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition json.hpp:2573
iterator end() noexcept
returns an iterator to one past the last element
Definition json.hpp:4751
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition json.hpp:6108
void clear() noexcept
clears the contents
Definition json.hpp:5372
friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition json.hpp:6760
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition json.hpp:7895
constexpr bool is_binary() const noexcept
return whether value is a binary array
Definition json.hpp:2776
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json object(initializer_list_t init={})
explicitly create an object from an initializer list
Definition json.hpp:1960
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition json.hpp:5787
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition json.hpp:8012
reference operator[](size_type idx)
access specified array element
Definition json.hpp:3681
friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
comparison: greater than
Definition json.hpp:6703
static void to_bson(const basic_json &j, detail::output_adapter< char > o)
Serializes the given JSON object j to BSON and forwards the corresponding BSON-representation to the ...
Definition json.hpp:7625
void update(const_iterator first, const_iterator last)
updates a JSON object from another object, overwriting existing keys
Definition json.hpp:6054
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:8273
void swap(binary_t &other)
exchanges the values
Definition json.hpp:6270
iter_impl< basic_json > iterator
an iterator for a basic_json container
Definition json.hpp:308
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
Definition json.hpp:314
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition json.hpp:7996
::nlohmann::json_pointer< basic_json > json_pointer
JSON Pointer, see nlohmann::json_pointer.
Definition json.hpp:239
friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
comparison: not equal
Definition json.hpp:6500
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
Definition json.hpp:4829
void swap(string_t &other)
exchanges the values
Definition json.hpp:6237
const_reference back() const
access the last element
Definition json.hpp:4169
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition json.hpp:6531
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init)
binary (stored with pointer to save storage)
Definition json.hpp:1860
constexpr bool is_string() const noexcept
return whether value is a string
Definition json.hpp:2754
constexpr bool is_array() const noexcept
return whether value is an array
Definition json.hpp:2732
iterator insert_iterator(const_iterator pos, Args &&... args)
Helper for insertion of an iterator.
Definition json.hpp:5726
basic_json flatten() const
return flattened JSON value
Definition json.hpp:8343
friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
comparison: greater than or equal
Definition json.hpp:6749
JSON_HEDLEY_RETURNS_NON_NULL const char * type_name() const noexcept
return the type as string
Definition json.hpp:7175
void push_back(basic_json &&val)
add an object to an array
Definition json.hpp:5451
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
Definition json.hpp:7752
size_type count(KeyT &&key) const
returns the number of occurrences of a key in a JSON object
Definition json.hpp:4577
constexpr bool is_number() const noexcept
return whether value is a number
Definition json.hpp:2603
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition json.hpp:6829
reference operator+=(initializer_list_t init)
add an object to an object
Definition json.hpp:5614
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition json.hpp:2632
std::initializer_list< detail::json_ref< basic_json > > initializer_list_t
helper type for initializer lists of basic_json values
Definition json.hpp:247
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition json.hpp:3831
iterator find(KeyT &&key)
find an element in a JSON object
Definition json.hpp:4526
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition json.hpp:1498
const_reference operator[](size_type idx) const
access specified array element
Definition json.hpp:3744
AllocatorType< basic_json > allocator_type
the allocator type
Definition json.hpp:300
nlohmann::byte_container_with_subtype< BinaryType > binary_t
a type for a packed binary type
Definition json.hpp:921
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:5540
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json parse(IteratorType first, IteratorType last, const parser_callback_t cb=nullptr, const bool allow_exceptions=true, const bool ignore_comments=false)
deserialize from a pair of character iterators
Definition json.hpp:6935
bool contains(const json_pointer &ptr) const
check the existence of an element in a JSON object given a JSON pointer
Definition json.hpp:4641
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition json.hpp:7879
basic_json patch(const basic_json &json_patch) const
applies a JSON patch
Definition json.hpp:8441
string_t value(const typename object_t::key_type &key, const char *default_value) const
overload for a default value of type const char*
Definition json.hpp:4011
basic_json(CompatibleType &&val) noexcept(noexcept(//NOLINT(bugprone-forwarding-reference-overload, bugprone-exception-escape) JSONSerializer< U >::to_json(std::declval< basic_json_t & >(), std::forward< CompatibleType >(val))))
create a JSON value
Definition json.hpp:1570
basic_json unflatten() const
unflatten a previously flattened JSON value
Definition json.hpp:8380
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition json.hpp:782
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:5565
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition json.hpp:4720
friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
comparison: less than or equal
Definition json.hpp:6657
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition json.hpp:7131
basic_json(initializer_list_t init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
Definition json.hpp:1732
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition json.hpp:3533
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition json.hpp:5765
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition json.hpp:2803
constexpr bool is_null() const noexcept
return whether value is null
Definition json.hpp:2551
friend void swap(reference left, reference right) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition json.hpp:6141
ObjectType< StringType, basic_json, object_comparator_t, AllocatorType< std::pair< const StringType, basic_json > > > object_t
a type for an object
Definition json.hpp:514
auto get() const noexcept(noexcept(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))) -> decltype(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))
get a (pointer) value (explicit)
Definition json.hpp:3207
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition json.hpp:5694
reference operator+=(const basic_json &val)
add an object to an array
Definition json.hpp:5514
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition json.hpp:4438
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition json.hpp:1987
static allocator_type get_allocator()
returns the allocator associated with the container
Definition json.hpp:322
constexpr auto get_ptr() const noexcept -> decltype(std::declval< const basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.hpp:3019
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition json.hpp:4821
an internal type for a backed binary type
Definition byte_container_with_subtype.hpp:25
BinaryType container_type
the type of the underlying container
Definition byte_container_with_subtype.hpp:28
std::uint64_t subtype_type
the type of the subtype
Definition byte_container_with_subtype.hpp:30
deserialization of CBOR, MessagePack, and UBJSON values
Definition binary_reader.hpp:60
bool sax_parse(const input_format_t format, json_sax_t *sax_, const bool strict=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
Definition binary_reader.hpp:97
serialization to CBOR and MessagePack values
Definition binary_writer.hpp:29
void write_bson(const BasicJsonType &j)
Definition binary_writer.hpp:49
general exception of the basic_json class
Definition exceptions.hpp:50
exception indicating errors with iterators
Definition exceptions.hpp:273
a template for a bidirectional iterator for the basic_json class This class implements a both iterato...
Definition iter_impl.hpp:40
typename BasicJsonType::difference_type difference_type
a type to represent differences between iterators
Definition iter_impl.hpp:67
internal_iterator< typename std::remove_const< BasicJsonType >::type > m_it
the actual iterator of the associated instance
Definition iter_impl.hpp:736
proxy class for the items() function
Definition iteration_proxy.hpp:122
Definition json_ref.hpp:14
a template for a reverse iterator class
Definition json_reverse_iterator.hpp:35
SAX implementation to create a JSON value from SAX events.
Definition json_sax.hpp:155
Definition lexer.hpp:27
exception indicating other library errors
Definition exceptions.hpp:415
exception indicating access out of the defined range
Definition exceptions.hpp:376
Definition output_adapters.hpp:115
exception indicating a parse error
Definition exceptions.hpp:185
static parse_error create(int id_, const position_t &pos, const std::string &what_arg, const BasicJsonType &context)
create a parse error exception
Definition exceptions.hpp:197
Definition primitive_iterator.hpp:22
Definition serializer.hpp:41
Definition input_adapters.hpp:456
exception indicating executing a member function with a wrong type
Definition exceptions.hpp:328
JSON Pointer.
Definition json_pointer.hpp:20
void pop_back()
remove last reference token
Definition json_pointer.hpp:247
const std::string & back() const
return last reference token
Definition json_pointer.hpp:271
bool empty() const noexcept
return whether pointer points to the root document
Definition json_pointer.hpp:318
_t< detail::count_< L, T > > count
Count the number of times a type T appears in the list L.
Definition meta.hpp:2725
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition value_t.hpp:67
value_t
the JSON type enumeration
Definition value_t.hpp:41
@ number_integer
number value (signed integer)
@ binary
binary array (ordered collection of bytes)
@ object
object (unordered set of name/value pairs)
@ number_float
number value (floating-point)
@ number_unsigned
number value (unsigned integer)
@ array
array (ordered collection of values)
cbor_tag_handler_t
how to treat CBOR tags
Definition binary_reader.hpp:32
parse_event_t
Definition parser.hpp:27
error_handler_t
how to treat decoding errors
Definition serializer.hpp:33
std::size_t hash(const BasicJsonType &j)
hash a JSON value
Definition hash.hpp:34
std::shared_ptr< output_adapter_protocol< CharType > > output_adapter_t
a type to simplify interfaces
Definition output_adapters.hpp:37
std::string escape(std::string s)
string escaping as described in RFC 6901 (Sect. 4)
Definition string_escape.hpp:42
input_format_t
the supported input formats
Definition input_adapters.hpp:26
namespace for Niels Lohmann
Definition adl_serializer.hpp:12
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition json.hpp:8969
Definition type_traits.hpp:154
Definition type_traits.hpp:96
an iterator value
Definition internal_iterator.hpp:16
BasicJsonType::array_t::iterator array_iterator
iterator for JSON arrays
Definition internal_iterator.hpp:20
BasicJsonType::object_t::iterator object_iterator
iterator for JSON objects
Definition internal_iterator.hpp:18
Definition type_traits.hpp:42
Definition type_traits.hpp:451
Definition type_traits.hpp:167
Definition detected.hpp:43
Definition type_traits.hpp:104
Definition type_traits.hpp:161
Definition cpp_future.hpp:140
SAX interface.
Definition json_sax.hpp:24
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
Definition json.hpp:8992
bool operator()(nlohmann::detail::value_t lhs, nlohmann::detail::value_t rhs) const noexcept
compare two value_t enum values
Definition json.hpp:9008