Horizon
json.hpp
1 /*
2  __ _____ _____ _____
3  __| | __| | | | JSON for Modern C++
4 | | |__ | | | | | | version 3.10.3
5 |_____|_____|_____|_|___| https://github.com/nlohmann/json
6 
7 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8 SPDX-License-Identifier: MIT
9 Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>.
10 
11 Permission is hereby granted, free of charge, to any person obtaining a copy
12 of this software and associated documentation files (the "Software"), to deal
13 in the Software without restriction, including without limitation the rights
14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 copies of the Software, and to permit persons to whom the Software is
16 furnished to do so, subject to the following conditions:
17 
18 The above copyright notice and this permission notice shall be included in all
19 copies or substantial portions of the Software.
20 
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 SOFTWARE.
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 
88 namespace nlohmann
89 {
90 
175 NLOHMANN_BASIC_JSON_TPL_DECLARATION
176 class 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 
292  using const_reference = const value_type&;
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
354  static basic_json meta()
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,
511  basic_json,
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 
1039  {
1041  break;
1042  }
1043 
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:
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:
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;
1628  JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
1629  break;
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;
1765 
1766  for (auto& element_ref : init)
1767  {
1768  auto element = element_ref.moved_or_copied();
1769  m_value.object->emplace(
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:
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  {
2096  {
2097  m_value.number_integer = first.m_object->m_value.number_integer;
2098  break;
2099  }
2100 
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 
2190  basic_json(const basic_json& other)
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 
2223  {
2224  m_value = other.m_value.number_integer;
2225  break;
2226  }
2227 
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 
2320  basic_json& operator=(basic_json other) noexcept (
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;
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:
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:
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 
4866  const_reverse_iterator rend() const noexcept
4867  {
4868  return crend();
4869  }
4870 
4896  {
4897  return const_reverse_iterator(cend());
4898  }
4899 
4925  {
4926  return const_reverse_iterator(cbegin());
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:
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:
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:
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  {
5377  {
5378  m_value.number_integer = 0;
5379  break;
5380  }
5381 
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 
5451  void push_back(basic_json&& val)
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;
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;
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;
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;
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;
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 
6391  return lhs.m_value.number_integer == rhs.m_value.number_integer;
6392 
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 
6558  return (lhs.m_value.number_integer) < (rhs.m_value.number_integer);
6559 
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";
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 
7618  {
7620  }
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 
8316  const_reference at(const json_pointer& ptr) const
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:
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 
8968 NLOHMANN_BASIC_JSON_TPL_DECLARATION
8969 std::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
8980 namespace std
8981 {
8982 
8984 template<>
8985 struct hash<nlohmann::json>
8986 {
8992  std::size_t operator()(const nlohmann::json& j) const
8993  {
8994  return nlohmann::detail::hash(j);
8995  }
8996 };
8997 
9001 template<>
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 
9023 template<>
9024 inline 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 
9049 JSON_HEDLEY_NON_NULL(1)
9050 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
9051 {
9052  return nlohmann::json::parse(s, s + n);
9053 }
9054 
9068 JSON_HEDLEY_NON_NULL(1)
9069 inline 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
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
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
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
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
static iteration_proxy< iterator > iterator_wrapper(reference ref) noexcept
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4988
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
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:2053
friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:6455
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
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
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
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:6829
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
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
JSON_HEDLEY_RETURNS_NON_NULL const char * type_name() const noexcept
return the type as string
Definition: json.hpp:7175
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
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
Definition: json.hpp:5078
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)
explicitly create a binary array (with subtype)
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
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
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 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
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:6805
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:2190
~basic_json() noexcept
destructor
Definition: json.hpp:2354
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 std::vector< std::uint8_t > to_cbor(const basic_json &j)
create a CBOR serialization of a given JSON value
Definition: json.hpp:7326
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
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
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
Definition: json.hpp:5070
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
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
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
binary_t & get_binary()
Definition: json.hpp:3428
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
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:7131
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init)
explicitly create a binary array (without subtype)
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
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
const binary_t & get_binary() const
Definition: json.hpp:3439
constexpr bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2603
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition: json.hpp:5694
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
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
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
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
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
void set_end() noexcept
set the iterator past the last value
Definition: iter_impl.hpp:230
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
const std::string & back() const
return last reference token
Definition: json_pointer.hpp:271
void pop_back()
remove last reference token
Definition: json_pointer.hpp:247
bool empty() const noexcept
return whether pointer points to the root document
Definition: json_pointer.hpp:318
std::function< struct zip_source *(struct zip *)> source
Source creation for adding files.
Definition: zip.hpp:122
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)
@ discarded
discarded by the parser callback function
@ 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
@ error
throw a parse_error exception in case of a tag
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: to_json.hpp:32
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:141
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