Horizon
json.hpp
1 /*
2  __ _____ _____ _____
3  __| | __| | | | JSON for Modern C++
4 | | |__ | | | | | | version 3.7.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 7
35 #define NLOHMANN_JSON_VERSION_PATCH 3
36 
37 #include <algorithm> // all_of, find, for_each
38 #include <cassert> // assert
39 #include <ciso646> // and, not, or
40 #include <cstddef> // nullptr_t, ptrdiff_t, size_t
41 #include <functional> // hash, less
42 #include <initializer_list> // initializer_list
43 #include <iosfwd> // istream, ostream
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/detail/conversions/from_json.hpp>
53 #include <nlohmann/detail/conversions/to_json.hpp>
54 #include <nlohmann/detail/exceptions.hpp>
55 #include <nlohmann/detail/input/binary_reader.hpp>
56 #include <nlohmann/detail/input/input_adapters.hpp>
57 #include <nlohmann/detail/input/lexer.hpp>
58 #include <nlohmann/detail/input/parser.hpp>
59 #include <nlohmann/detail/iterators/internal_iterator.hpp>
60 #include <nlohmann/detail/iterators/iter_impl.hpp>
61 #include <nlohmann/detail/iterators/iteration_proxy.hpp>
62 #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
63 #include <nlohmann/detail/iterators/primitive_iterator.hpp>
64 #include <nlohmann/detail/json_pointer.hpp>
65 #include <nlohmann/detail/json_ref.hpp>
66 #include <nlohmann/detail/macro_scope.hpp>
67 #include <nlohmann/detail/meta/cpp_future.hpp>
68 #include <nlohmann/detail/meta/type_traits.hpp>
69 #include <nlohmann/detail/output/binary_writer.hpp>
70 #include <nlohmann/detail/output/output_adapters.hpp>
71 #include <nlohmann/detail/output/serializer.hpp>
72 #include <nlohmann/detail/value_t.hpp>
73 #include <nlohmann/json_fwd.hpp>
74 
80 namespace nlohmann
81 {
82 
164 NLOHMANN_BASIC_JSON_TPL_DECLARATION
165 class basic_json
166 {
167  private:
168  template<detail::value_t> friend struct detail::external_constructor;
169  friend ::nlohmann::json_pointer<basic_json>;
170  friend ::nlohmann::detail::parser<basic_json>;
171  friend ::nlohmann::detail::serializer<basic_json>;
172  template<typename BasicJsonType>
173  friend class ::nlohmann::detail::iter_impl;
174  template<typename BasicJsonType, typename CharType>
175  friend class ::nlohmann::detail::binary_writer;
176  template<typename BasicJsonType, typename SAX>
177  friend class ::nlohmann::detail::binary_reader;
178  template<typename BasicJsonType>
179  friend class ::nlohmann::detail::json_sax_dom_parser;
180  template<typename BasicJsonType>
181  friend class ::nlohmann::detail::json_sax_dom_callback_parser;
182 
184  using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
185 
186  // convenience aliases for types residing in namespace detail;
189 
190  using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
191  template<typename BasicJsonType>
193  template<typename BasicJsonType>
195  template<typename Iterator>
196  using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
197  template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
198 
199  template<typename CharType>
200  using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
201 
202  using binary_reader = ::nlohmann::detail::binary_reader<basic_json>;
203  template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
204 
206 
207  public:
208  using value_t = detail::value_t;
211  template<typename T, typename SFINAE>
212  using json_serializer = JSONSerializer<T, SFINAE>;
216  using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
217 
221 
223  // exceptions //
225 
229 
242 
244 
245 
247  // container types //
249 
254 
257 
261  using const_reference = const value_type&;
262 
264  using difference_type = std::ptrdiff_t;
266  using size_type = std::size_t;
267 
269  using allocator_type = AllocatorType<basic_json>;
270 
272  using pointer = typename std::allocator_traits<allocator_type>::pointer;
274  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
275 
284 
286 
287 
292  {
293  return allocator_type();
294  }
295 
322  JSON_HEDLEY_WARN_UNUSED_RESULT
323  static basic_json meta()
324  {
325  basic_json result;
326 
327  result["copyright"] = "(C) 2013-2017 Niels Lohmann";
328  result["name"] = "JSON for Modern C++";
329  result["url"] = "https://github.com/nlohmann/json";
330  result["version"]["string"] =
331  std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." +
332  std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." +
333  std::to_string(NLOHMANN_JSON_VERSION_PATCH);
334  result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
335  result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
336  result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
337 
338 #ifdef _WIN32
339  result["platform"] = "win32";
340 #elif defined __linux__
341  result["platform"] = "linux";
342 #elif defined __APPLE__
343  result["platform"] = "apple";
344 #elif defined __unix__
345  result["platform"] = "unix";
346 #else
347  result["platform"] = "unknown";
348 #endif
349 
350 #if defined(__ICC) || defined(__INTEL_COMPILER)
351  result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
352 #elif defined(__clang__)
353  result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
354 #elif defined(__GNUC__) || defined(__GNUG__)
355  result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
356 #elif defined(__HP_cc) || defined(__HP_aCC)
357  result["compiler"] = "hp"
358 #elif defined(__IBMCPP__)
359  result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
360 #elif defined(_MSC_VER)
361  result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
362 #elif defined(__PGI)
363  result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
364 #elif defined(__SUNPRO_CC)
365  result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
366 #else
367  result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
368 #endif
369 
370 #ifdef __cplusplus
371  result["compiler"]["c++"] = std::to_string(__cplusplus);
372 #else
373  result["compiler"]["c++"] = "unknown";
374 #endif
375  return result;
376  }
377 
378 
380  // JSON value data types //
382 
387 
388 #if defined(JSON_HAS_CPP_14)
389  // Use transparent comparator if possible, combined with perfect forwarding
390  // on find() and count() calls prevents unnecessary string construction.
391  using object_comparator_t = std::less<>;
392 #else
393  using object_comparator_t = std::less<StringType>;
394 #endif
395 
479  using object_t = ObjectType<StringType,
480  basic_json,
481  object_comparator_t,
482  AllocatorType<std::pair<const StringType,
483  basic_json>>>;
484 
529  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
530 
582  using string_t = StringType;
583 
608  using boolean_t = BooleanType;
609 
680  using number_integer_t = NumberIntegerType;
681 
751  using number_unsigned_t = NumberUnsignedType;
752 
819  using number_float_t = NumberFloatType;
820 
822 
823  private:
824 
826  template<typename T, typename... Args>
827  JSON_HEDLEY_RETURNS_NON_NULL
828  static T* create(Args&& ... args)
829  {
830  AllocatorType<T> alloc;
831  using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
832 
833  auto deleter = [&](T * object)
834  {
835  AllocatorTraits::deallocate(alloc, object, 1);
836  };
837  std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
838  AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
839  assert(object != nullptr);
840  return object.release();
841  }
842 
844  // JSON value storage //
846 
871  union json_value
872  {
874  object_t* object;
876  array_t* array;
878  string_t* string;
880  boolean_t boolean;
882  number_integer_t number_integer;
884  number_unsigned_t number_unsigned;
886  number_float_t number_float;
887 
889  json_value() = default;
891  json_value(boolean_t v) noexcept : boolean(v) {}
893  json_value(number_integer_t v) noexcept : number_integer(v) {}
895  json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
897  json_value(number_float_t v) noexcept : number_float(v) {}
899  json_value(value_t t)
900  {
901  switch (t)
902  {
903  case value_t::object:
904  {
905  object = create<object_t>();
906  break;
907  }
908 
909  case value_t::array:
910  {
911  array = create<array_t>();
912  break;
913  }
914 
915  case value_t::string:
916  {
917  string = create<string_t>("");
918  break;
919  }
920 
921  case value_t::boolean:
922  {
923  boolean = boolean_t(false);
924  break;
925  }
926 
928  {
929  number_integer = number_integer_t(0);
930  break;
931  }
932 
934  {
935  number_unsigned = number_unsigned_t(0);
936  break;
937  }
938 
940  {
941  number_float = number_float_t(0.0);
942  break;
943  }
944 
945  case value_t::null:
946  {
947  object = nullptr; // silence warning, see #821
948  break;
949  }
950 
951  default:
952  {
953  object = nullptr; // silence warning, see #821
954  if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
955  {
956  JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.7.3")); // LCOV_EXCL_LINE
957  }
958  break;
959  }
960  }
961  }
962 
964  json_value(const string_t& value)
965  {
966  string = create<string_t>(value);
967  }
968 
970  json_value(string_t&& value)
971  {
972  string = create<string_t>(std::move(value));
973  }
974 
976  json_value(const object_t& value)
977  {
978  object = create<object_t>(value);
979  }
980 
982  json_value(object_t&& value)
983  {
984  object = create<object_t>(std::move(value));
985  }
986 
988  json_value(const array_t& value)
989  {
990  array = create<array_t>(value);
991  }
992 
994  json_value(array_t&& value)
995  {
996  array = create<array_t>(std::move(value));
997  }
998 
999  void destroy(value_t t) noexcept
1000  {
1001  // flatten the current json_value to a heap-allocated stack
1002  std::vector<basic_json> stack;
1003 
1004  // move the top-level items to stack
1005  if (t == value_t::array)
1006  {
1007  stack.reserve(array->size());
1008  std::move(array->begin(), array->end(), std::back_inserter(stack));
1009  }
1010  else if (t == value_t::object)
1011  {
1012  stack.reserve(object->size());
1013  for (auto&& it : *object)
1014  {
1015  stack.push_back(std::move(it.second));
1016  }
1017  }
1018 
1019  while (not stack.empty())
1020  {
1021  // move the last item to local variable to be processed
1022  basic_json current_item(std::move(stack.back()));
1023  stack.pop_back();
1024 
1025  // if current_item is array/object, move
1026  // its children to the stack to be processed later
1027  if (current_item.is_array())
1028  {
1029  std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(),
1030  std::back_inserter(stack));
1031 
1032  current_item.m_value.array->clear();
1033  }
1034  else if (current_item.is_object())
1035  {
1036  for (auto&& it : *current_item.m_value.object)
1037  {
1038  stack.push_back(std::move(it.second));
1039  }
1040 
1041  current_item.m_value.object->clear();
1042  }
1043 
1044  // it's now safe that current_item get destructed
1045  // since it doesn't have any children
1046  }
1047 
1048  switch (t)
1049  {
1050  case value_t::object:
1051  {
1052  AllocatorType<object_t> alloc;
1053  std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
1054  std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
1055  break;
1056  }
1057 
1058  case value_t::array:
1059  {
1060  AllocatorType<array_t> alloc;
1061  std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
1062  std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
1063  break;
1064  }
1065 
1066  case value_t::string:
1067  {
1068  AllocatorType<string_t> alloc;
1069  std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
1070  std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
1071  break;
1072  }
1073 
1074  default:
1075  {
1076  break;
1077  }
1078  }
1079  }
1080  };
1081 
1091  void assert_invariant() const noexcept
1092  {
1093  assert(m_type != value_t::object or m_value.object != nullptr);
1094  assert(m_type != value_t::array or m_value.array != nullptr);
1095  assert(m_type != value_t::string or m_value.string != nullptr);
1096  }
1097 
1098  public:
1100  // JSON parser callback //
1102 
1119 
1169  using parser_callback_t = typename parser::parser_callback_t;
1170 
1172  // constructors //
1174 
1179 
1210  : m_type(v), m_value(v)
1211  {
1212  assert_invariant();
1213  }
1214 
1233  basic_json(std::nullptr_t = nullptr) noexcept
1234  : basic_json(value_t::null)
1235  {
1236  assert_invariant();
1237  }
1238 
1296  template <typename CompatibleType,
1297  typename U = detail::uncvref_t<CompatibleType>,
1298  detail::enable_if_t<
1300  basic_json(CompatibleType && val) noexcept(noexcept(
1301  JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
1302  std::forward<CompatibleType>(val))))
1303  {
1304  JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
1305  assert_invariant();
1306  }
1307 
1334  template <typename BasicJsonType,
1335  detail::enable_if_t<
1336  detail::is_basic_json<BasicJsonType>::value and not std::is_same<basic_json, BasicJsonType>::value, int> = 0>
1337  basic_json(const BasicJsonType& val)
1338  {
1339  using other_boolean_t = typename BasicJsonType::boolean_t;
1340  using other_number_float_t = typename BasicJsonType::number_float_t;
1341  using other_number_integer_t = typename BasicJsonType::number_integer_t;
1342  using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
1343  using other_string_t = typename BasicJsonType::string_t;
1344  using other_object_t = typename BasicJsonType::object_t;
1345  using other_array_t = typename BasicJsonType::array_t;
1346 
1347  switch (val.type())
1348  {
1349  case value_t::boolean:
1350  JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
1351  break;
1352  case value_t::number_float:
1353  JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
1354  break;
1356  JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
1357  break;
1359  JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
1360  break;
1361  case value_t::string:
1362  JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
1363  break;
1364  case value_t::object:
1365  JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
1366  break;
1367  case value_t::array:
1368  JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
1369  break;
1370  case value_t::null:
1371  *this = nullptr;
1372  break;
1373  case value_t::discarded:
1374  m_type = value_t::discarded;
1375  break;
1376  default: // LCOV_EXCL_LINE
1377  assert(false); // LCOV_EXCL_LINE
1378  }
1379  assert_invariant();
1380  }
1381 
1457  bool type_deduction = true,
1458  value_t manual_type = value_t::array)
1459  {
1460  // check if each element is an array with two elements whose first
1461  // element is a string
1462  bool is_an_object = std::all_of(init.begin(), init.end(),
1463  [](const detail::json_ref<basic_json>& element_ref)
1464  {
1465  return element_ref->is_array() and element_ref->size() == 2 and (*element_ref)[0].is_string();
1466  });
1467 
1468  // adjust type if type deduction is not wanted
1469  if (not type_deduction)
1470  {
1471  // if array is wanted, do not create an object though possible
1472  if (manual_type == value_t::array)
1473  {
1474  is_an_object = false;
1475  }
1476 
1477  // if object is wanted but impossible, throw an exception
1478  if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object and not is_an_object))
1479  {
1480  JSON_THROW(type_error::create(301, "cannot create object from initializer list"));
1481  }
1482  }
1483 
1484  if (is_an_object)
1485  {
1486  // the initializer list is a list of pairs -> create object
1487  m_type = value_t::object;
1488  m_value = value_t::object;
1489 
1490  std::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref)
1491  {
1492  auto element = element_ref.moved_or_copied();
1493  m_value.object->emplace(
1494  std::move(*((*element.m_value.array)[0].m_value.string)),
1495  std::move((*element.m_value.array)[1]));
1496  });
1497  }
1498  else
1499  {
1500  // the initializer list describes an array -> create array
1501  m_type = value_t::array;
1502  m_value.array = create<array_t>(init.begin(), init.end());
1503  }
1504 
1505  assert_invariant();
1506  }
1507 
1545  JSON_HEDLEY_WARN_UNUSED_RESULT
1547  {
1548  return basic_json(init, false, value_t::array);
1549  }
1550 
1589  JSON_HEDLEY_WARN_UNUSED_RESULT
1591  {
1592  return basic_json(init, false, value_t::object);
1593  }
1594 
1618  : m_type(value_t::array)
1619  {
1620  m_value.array = create<array_t>(cnt, val);
1621  assert_invariant();
1622  }
1623 
1679  template<class InputIT, typename std::enable_if<
1680  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1681  std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>
1682  basic_json(InputIT first, InputIT last)
1683  {
1684  assert(first.m_object != nullptr);
1685  assert(last.m_object != nullptr);
1686 
1687  // make sure iterator fits the current value
1688  if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
1689  {
1690  JSON_THROW(invalid_iterator::create(201, "iterators are not compatible"));
1691  }
1692 
1693  // copy type from first iterator
1694  m_type = first.m_object->m_type;
1695 
1696  // check if iterator range is complete for primitive values
1697  switch (m_type)
1698  {
1699  case value_t::boolean:
1700  case value_t::number_float:
1703  case value_t::string:
1704  {
1705  if (JSON_HEDLEY_UNLIKELY(not first.m_it.primitive_iterator.is_begin()
1706  or not last.m_it.primitive_iterator.is_end()))
1707  {
1708  JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
1709  }
1710  break;
1711  }
1712 
1713  default:
1714  break;
1715  }
1716 
1717  switch (m_type)
1718  {
1720  {
1721  m_value.number_integer = first.m_object->m_value.number_integer;
1722  break;
1723  }
1724 
1726  {
1727  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1728  break;
1729  }
1730 
1731  case value_t::number_float:
1732  {
1733  m_value.number_float = first.m_object->m_value.number_float;
1734  break;
1735  }
1736 
1737  case value_t::boolean:
1738  {
1739  m_value.boolean = first.m_object->m_value.boolean;
1740  break;
1741  }
1742 
1743  case value_t::string:
1744  {
1745  m_value = *first.m_object->m_value.string;
1746  break;
1747  }
1748 
1749  case value_t::object:
1750  {
1751  m_value.object = create<object_t>(first.m_it.object_iterator,
1752  last.m_it.object_iterator);
1753  break;
1754  }
1755 
1756  case value_t::array:
1757  {
1758  m_value.array = create<array_t>(first.m_it.array_iterator,
1759  last.m_it.array_iterator);
1760  break;
1761  }
1762 
1763  default:
1764  JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " +
1765  std::string(first.m_object->type_name())));
1766  }
1767 
1768  assert_invariant();
1769  }
1770 
1771 
1773  // other constructors and destructor //
1775 
1778  : basic_json(ref.moved_or_copied())
1779  {}
1780 
1806  basic_json(const basic_json& other)
1807  : m_type(other.m_type)
1808  {
1809  // check of passed value is valid
1810  other.assert_invariant();
1811 
1812  switch (m_type)
1813  {
1814  case value_t::object:
1815  {
1816  m_value = *other.m_value.object;
1817  break;
1818  }
1819 
1820  case value_t::array:
1821  {
1822  m_value = *other.m_value.array;
1823  break;
1824  }
1825 
1826  case value_t::string:
1827  {
1828  m_value = *other.m_value.string;
1829  break;
1830  }
1831 
1832  case value_t::boolean:
1833  {
1834  m_value = other.m_value.boolean;
1835  break;
1836  }
1837 
1839  {
1840  m_value = other.m_value.number_integer;
1841  break;
1842  }
1843 
1845  {
1846  m_value = other.m_value.number_unsigned;
1847  break;
1848  }
1849 
1850  case value_t::number_float:
1851  {
1852  m_value = other.m_value.number_float;
1853  break;
1854  }
1855 
1856  default:
1857  break;
1858  }
1859 
1860  assert_invariant();
1861  }
1862 
1889  basic_json(basic_json&& other) noexcept
1890  : m_type(std::move(other.m_type)),
1891  m_value(std::move(other.m_value))
1892  {
1893  // check that passed value is valid
1894  other.assert_invariant();
1895 
1896  // invalidate payload
1897  other.m_type = value_t::null;
1898  other.m_value = {};
1899 
1900  assert_invariant();
1901  }
1902 
1926  basic_json& operator=(basic_json other) noexcept (
1927  std::is_nothrow_move_constructible<value_t>::value and
1928  std::is_nothrow_move_assignable<value_t>::value and
1929  std::is_nothrow_move_constructible<json_value>::value and
1930  std::is_nothrow_move_assignable<json_value>::value
1931  )
1932  {
1933  // check that passed value is valid
1934  other.assert_invariant();
1935 
1936  using std::swap;
1937  swap(m_type, other.m_type);
1938  swap(m_value, other.m_value);
1939 
1940  assert_invariant();
1941  return *this;
1942  }
1943 
1959  ~basic_json() noexcept
1960  {
1961  assert_invariant();
1962  m_value.destroy(m_type);
1963  }
1964 
1966 
1967  public:
1969  // object inspection //
1971 
1975 
2017  string_t dump(const int indent = -1,
2018  const char indent_char = ' ',
2019  const bool ensure_ascii = false,
2020  const error_handler_t error_handler = error_handler_t::strict) const
2021  {
2022  string_t result;
2023  serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
2024 
2025  if (indent >= 0)
2026  {
2027  s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
2028  }
2029  else
2030  {
2031  s.dump(*this, false, ensure_ascii, 0);
2032  }
2033 
2034  return result;
2035  }
2036 
2069  constexpr value_t type() const noexcept
2070  {
2071  return m_type;
2072  }
2073 
2099  constexpr bool is_primitive() const noexcept
2100  {
2101  return is_null() or is_string() or is_boolean() or is_number();
2102  }
2103 
2126  constexpr bool is_structured() const noexcept
2127  {
2128  return is_array() or is_object();
2129  }
2130 
2148  constexpr bool is_null() const noexcept
2149  {
2150  return m_type == value_t::null;
2151  }
2152 
2170  constexpr bool is_boolean() const noexcept
2171  {
2172  return m_type == value_t::boolean;
2173  }
2174 
2200  constexpr bool is_number() const noexcept
2201  {
2202  return is_number_integer() or is_number_float();
2203  }
2204 
2229  constexpr bool is_number_integer() const noexcept
2230  {
2231  return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2232  }
2233 
2257  constexpr bool is_number_unsigned() const noexcept
2258  {
2259  return m_type == value_t::number_unsigned;
2260  }
2261 
2285  constexpr bool is_number_float() const noexcept
2286  {
2287  return m_type == value_t::number_float;
2288  }
2289 
2307  constexpr bool is_object() const noexcept
2308  {
2309  return m_type == value_t::object;
2310  }
2311 
2329  constexpr bool is_array() const noexcept
2330  {
2331  return m_type == value_t::array;
2332  }
2333 
2351  constexpr bool is_string() const noexcept
2352  {
2353  return m_type == value_t::string;
2354  }
2355 
2378  constexpr bool is_discarded() const noexcept
2379  {
2380  return m_type == value_t::discarded;
2381  }
2382 
2404  constexpr operator value_t() const noexcept
2405  {
2406  return m_type;
2407  }
2408 
2410 
2411  private:
2413  // value access //
2415 
2417  boolean_t get_impl(boolean_t* /*unused*/) const
2418  {
2419  if (JSON_HEDLEY_LIKELY(is_boolean()))
2420  {
2421  return m_value.boolean;
2422  }
2423 
2424  JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name())));
2425  }
2426 
2428  object_t* get_impl_ptr(object_t* /*unused*/) noexcept
2429  {
2430  return is_object() ? m_value.object : nullptr;
2431  }
2432 
2434  constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
2435  {
2436  return is_object() ? m_value.object : nullptr;
2437  }
2438 
2440  array_t* get_impl_ptr(array_t* /*unused*/) noexcept
2441  {
2442  return is_array() ? m_value.array : nullptr;
2443  }
2444 
2446  constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
2447  {
2448  return is_array() ? m_value.array : nullptr;
2449  }
2450 
2452  string_t* get_impl_ptr(string_t* /*unused*/) noexcept
2453  {
2454  return is_string() ? m_value.string : nullptr;
2455  }
2456 
2458  constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
2459  {
2460  return is_string() ? m_value.string : nullptr;
2461  }
2462 
2464  boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
2465  {
2466  return is_boolean() ? &m_value.boolean : nullptr;
2467  }
2468 
2470  constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
2471  {
2472  return is_boolean() ? &m_value.boolean : nullptr;
2473  }
2474 
2476  number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
2477  {
2478  return is_number_integer() ? &m_value.number_integer : nullptr;
2479  }
2480 
2482  constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
2483  {
2484  return is_number_integer() ? &m_value.number_integer : nullptr;
2485  }
2486 
2488  number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
2489  {
2490  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2491  }
2492 
2494  constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
2495  {
2496  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2497  }
2498 
2500  number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
2501  {
2502  return is_number_float() ? &m_value.number_float : nullptr;
2503  }
2504 
2506  constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
2507  {
2508  return is_number_float() ? &m_value.number_float : nullptr;
2509  }
2510 
2522  template<typename ReferenceType, typename ThisType>
2523  static ReferenceType get_ref_impl(ThisType& obj)
2524  {
2525  // delegate the call to get_ptr<>()
2526  auto ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
2527 
2528  if (JSON_HEDLEY_LIKELY(ptr != nullptr))
2529  {
2530  return *ptr;
2531  }
2532 
2533  JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name())));
2534  }
2535 
2536  public:
2540 
2555  template<typename BasicJsonType, detail::enable_if_t<
2556  std::is_same<typename std::remove_const<BasicJsonType>::type, basic_json_t>::value,
2557  int> = 0>
2558  basic_json get() const
2559  {
2560  return *this;
2561  }
2562 
2578  template<typename BasicJsonType, detail::enable_if_t<
2579  not std::is_same<BasicJsonType, basic_json>::value and
2581  BasicJsonType get() const
2582  {
2583  return *this;
2584  }
2585 
2625  template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
2626  detail::enable_if_t <
2627  not detail::is_basic_json<ValueType>::value and
2628  detail::has_from_json<basic_json_t, ValueType>::value and
2629  not detail::has_non_default_from_json<basic_json_t, ValueType>::value,
2630  int> = 0>
2631  ValueType get() const noexcept(noexcept(
2632  JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
2633  {
2634  // we cannot static_assert on ValueTypeCV being non-const, because
2635  // there is support for get<const basic_json_t>(), which is why we
2636  // still need the uncvref
2637  static_assert(not std::is_reference<ValueTypeCV>::value,
2638  "get() cannot be used with reference types, you might want to use get_ref()");
2639  static_assert(std::is_default_constructible<ValueType>::value,
2640  "types must be DefaultConstructible when used with get()");
2641 
2642  ValueType ret;
2643  JSONSerializer<ValueType>::from_json(*this, ret);
2644  return ret;
2645  }
2646 
2678  template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
2679  detail::enable_if_t<not std::is_same<basic_json_t, ValueType>::value and
2680  detail::has_non_default_from_json<basic_json_t, ValueType>::value,
2681  int> = 0>
2682  ValueType get() const noexcept(noexcept(
2683  JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
2684  {
2685  static_assert(not std::is_reference<ValueTypeCV>::value,
2686  "get() cannot be used with reference types, you might want to use get_ref()");
2687  return JSONSerializer<ValueType>::from_json(*this);
2688  }
2689 
2723  template<typename ValueType,
2724  detail::enable_if_t <
2727  int> = 0>
2728  ValueType & get_to(ValueType& v) const noexcept(noexcept(
2729  JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
2730  {
2731  JSONSerializer<ValueType>::from_json(*this, v);
2732  return v;
2733  }
2734 
2735  template <
2736  typename T, std::size_t N,
2737  typename Array = T (&)[N],
2738  detail::enable_if_t <
2740  Array get_to(T (&v)[N]) const
2741  noexcept(noexcept(JSONSerializer<Array>::from_json(
2742  std::declval<const basic_json_t&>(), v)))
2743  {
2744  JSONSerializer<Array>::from_json(*this, v);
2745  return v;
2746  }
2747 
2748 
2775  template<typename PointerType, typename std::enable_if<
2776  std::is_pointer<PointerType>::value, int>::type = 0>
2777  auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
2778  {
2779  // delegate the call to get_impl_ptr<>()
2780  return get_impl_ptr(static_cast<PointerType>(nullptr));
2781  }
2782 
2787  template<typename PointerType, typename std::enable_if<
2788  std::is_pointer<PointerType>::value and
2789  std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
2790  constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
2791  {
2792  // delegate the call to get_impl_ptr<>() const
2793  return get_impl_ptr(static_cast<PointerType>(nullptr));
2794  }
2795 
2823  template<typename PointerType, typename std::enable_if<
2824  std::is_pointer<PointerType>::value, int>::type = 0>
2825  auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
2826  {
2827  // delegate the call to get_ptr
2828  return get_ptr<PointerType>();
2829  }
2830 
2835  template<typename PointerType, typename std::enable_if<
2836  std::is_pointer<PointerType>::value, int>::type = 0>
2837  constexpr auto get() const noexcept -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
2838  {
2839  // delegate the call to get_ptr
2840  return get_ptr<PointerType>();
2841  }
2842 
2869  template<typename ReferenceType, typename std::enable_if<
2870  std::is_reference<ReferenceType>::value, int>::type = 0>
2871  ReferenceType get_ref()
2872  {
2873  // delegate call to get_ref_impl
2874  return get_ref_impl<ReferenceType>(*this);
2875  }
2876 
2881  template<typename ReferenceType, typename std::enable_if<
2882  std::is_reference<ReferenceType>::value and
2883  std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
2884  ReferenceType get_ref() const
2885  {
2886  // delegate call to get_ref_impl
2887  return get_ref_impl<ReferenceType>(*this);
2888  }
2889 
2919  template < typename ValueType, typename std::enable_if <
2920  not std::is_pointer<ValueType>::value and
2921  not std::is_same<ValueType, detail::json_ref<basic_json>>::value and
2922  not std::is_same<ValueType, typename string_t::value_type>::value and
2924 
2925 #ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015
2926  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
2927 #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) and _MSC_VER <= 1914))
2928  and not std::is_same<ValueType, typename std::string_view>::value
2929 #endif
2930 #endif
2931  and detail::is_detected<detail::get_template_function, const basic_json_t&, ValueType>::value
2932  , int >::type = 0 >
2933  operator ValueType() const
2934  {
2935  // delegate the call to get<>() const
2936  return get<ValueType>();
2937  }
2938 
2940 
2941 
2943  // element access //
2945 
2949 
2977  {
2978  // at only works for arrays
2979  if (JSON_HEDLEY_LIKELY(is_array()))
2980  {
2981  JSON_TRY
2982  {
2983  return m_value.array->at(idx);
2984  }
2985  JSON_CATCH (std::out_of_range&)
2986  {
2987  // create better exception explanation
2988  JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
2989  }
2990  }
2991  else
2992  {
2993  JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
2994  }
2995  }
2996 
3024  {
3025  // at only works for arrays
3026  if (JSON_HEDLEY_LIKELY(is_array()))
3027  {
3028  JSON_TRY
3029  {
3030  return m_value.array->at(idx);
3031  }
3032  JSON_CATCH (std::out_of_range&)
3033  {
3034  // create better exception explanation
3035  JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
3036  }
3037  }
3038  else
3039  {
3040  JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
3041  }
3042  }
3043 
3074  reference at(const typename object_t::key_type& key)
3075  {
3076  // at only works for objects
3077  if (JSON_HEDLEY_LIKELY(is_object()))
3078  {
3079  JSON_TRY
3080  {
3081  return m_value.object->at(key);
3082  }
3083  JSON_CATCH (std::out_of_range&)
3084  {
3085  // create better exception explanation
3086  JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
3087  }
3088  }
3089  else
3090  {
3091  JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
3092  }
3093  }
3094 
3125  const_reference at(const typename object_t::key_type& key) const
3126  {
3127  // at only works for objects
3128  if (JSON_HEDLEY_LIKELY(is_object()))
3129  {
3130  JSON_TRY
3131  {
3132  return m_value.object->at(key);
3133  }
3134  JSON_CATCH (std::out_of_range&)
3135  {
3136  // create better exception explanation
3137  JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
3138  }
3139  }
3140  else
3141  {
3142  JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
3143  }
3144  }
3145 
3172  {
3173  // implicitly convert null value to an empty array
3174  if (is_null())
3175  {
3176  m_type = value_t::array;
3177  m_value.array = create<array_t>();
3178  assert_invariant();
3179  }
3180 
3181  // operator[] only works for arrays
3182  if (JSON_HEDLEY_LIKELY(is_array()))
3183  {
3184  // fill up array with null values if given idx is outside range
3185  if (idx >= m_value.array->size())
3186  {
3187  m_value.array->insert(m_value.array->end(),
3188  idx - m_value.array->size() + 1,
3189  basic_json());
3190  }
3191 
3192  return m_value.array->operator[](idx);
3193  }
3194 
3195  JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
3196  }
3197 
3218  {
3219  // const operator[] only works for arrays
3220  if (JSON_HEDLEY_LIKELY(is_array()))
3221  {
3222  return m_value.array->operator[](idx);
3223  }
3224 
3225  JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
3226  }
3227 
3255  reference operator[](const typename object_t::key_type& key)
3256  {
3257  // implicitly convert null value to an empty object
3258  if (is_null())
3259  {
3260  m_type = value_t::object;
3261  m_value.object = create<object_t>();
3262  assert_invariant();
3263  }
3264 
3265  // operator[] only works for objects
3266  if (JSON_HEDLEY_LIKELY(is_object()))
3267  {
3268  return m_value.object->operator[](key);
3269  }
3270 
3271  JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
3272  }
3273 
3304  const_reference operator[](const typename object_t::key_type& key) const
3305  {
3306  // const operator[] only works for objects
3307  if (JSON_HEDLEY_LIKELY(is_object()))
3308  {
3309  assert(m_value.object->find(key) != m_value.object->end());
3310  return m_value.object->find(key)->second;
3311  }
3312 
3313  JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
3314  }
3315 
3343  template<typename T>
3344  JSON_HEDLEY_NON_NULL(2)
3345  reference operator[](T* key)
3346  {
3347  // implicitly convert null to object
3348  if (is_null())
3349  {
3350  m_type = value_t::object;
3351  m_value = value_t::object;
3352  assert_invariant();
3353  }
3354 
3355  // at only works for objects
3356  if (JSON_HEDLEY_LIKELY(is_object()))
3357  {
3358  return m_value.object->operator[](key);
3359  }
3360 
3361  JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
3362  }
3363 
3394  template<typename T>
3395  JSON_HEDLEY_NON_NULL(2)
3396  const_reference operator[](T* key) const
3397  {
3398  // at only works for objects
3399  if (JSON_HEDLEY_LIKELY(is_object()))
3400  {
3401  assert(m_value.object->find(key) != m_value.object->end());
3402  return m_value.object->find(key)->second;
3403  }
3404 
3405  JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
3406  }
3407 
3458  template<class ValueType, typename std::enable_if<
3459  std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
3460  ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
3461  {
3462  // at only works for objects
3463  if (JSON_HEDLEY_LIKELY(is_object()))
3464  {
3465  // if key is found, return value and given default value otherwise
3466  const auto it = find(key);
3467  if (it != end())
3468  {
3469  return *it;
3470  }
3471 
3472  return default_value;
3473  }
3474 
3475  JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
3476  }
3477 
3482  string_t value(const typename object_t::key_type& key, const char* default_value) const
3483  {
3484  return value(key, string_t(default_value));
3485  }
3486 
3530  template<class ValueType, typename std::enable_if<
3531  std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
3532  ValueType value(const json_pointer& ptr, const ValueType& default_value) const
3533  {
3534  // at only works for objects
3535  if (JSON_HEDLEY_LIKELY(is_object()))
3536  {
3537  // if pointer resolves a value, return it or use default value
3538  JSON_TRY
3539  {
3540  return ptr.get_checked(this);
3541  }
3542  JSON_INTERNAL_CATCH (out_of_range&)
3543  {
3544  return default_value;
3545  }
3546  }
3547 
3548  JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
3549  }
3550 
3555  JSON_HEDLEY_NON_NULL(3)
3556  string_t value(const json_pointer& ptr, const char* default_value) const
3557  {
3558  return value(ptr, string_t(default_value));
3559  }
3560 
3587  {
3588  return *begin();
3589  }
3590 
3595  {
3596  return *cbegin();
3597  }
3598 
3631  {
3632  auto tmp = end();
3633  --tmp;
3634  return *tmp;
3635  }
3636 
3641  {
3642  auto tmp = cend();
3643  --tmp;
3644  return *tmp;
3645  }
3646 
3693  template<class IteratorType, typename std::enable_if<
3694  std::is_same<IteratorType, typename basic_json_t::iterator>::value or
3695  std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
3696  = 0>
3697  IteratorType erase(IteratorType pos)
3698  {
3699  // make sure iterator fits the current value
3700  if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
3701  {
3702  JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
3703  }
3704 
3705  IteratorType result = end();
3706 
3707  switch (m_type)
3708  {
3709  case value_t::boolean:
3710  case value_t::number_float:
3713  case value_t::string:
3714  {
3715  if (JSON_HEDLEY_UNLIKELY(not pos.m_it.primitive_iterator.is_begin()))
3716  {
3717  JSON_THROW(invalid_iterator::create(205, "iterator out of range"));
3718  }
3719 
3720  if (is_string())
3721  {
3722  AllocatorType<string_t> alloc;
3723  std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
3724  std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
3725  m_value.string = nullptr;
3726  }
3727 
3728  m_type = value_t::null;
3729  assert_invariant();
3730  break;
3731  }
3732 
3733  case value_t::object:
3734  {
3735  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3736  break;
3737  }
3738 
3739  case value_t::array:
3740  {
3741  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3742  break;
3743  }
3744 
3745  default:
3746  JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
3747  }
3748 
3749  return result;
3750  }
3751 
3798  template<class IteratorType, typename std::enable_if<
3799  std::is_same<IteratorType, typename basic_json_t::iterator>::value or
3800  std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
3801  = 0>
3802  IteratorType erase(IteratorType first, IteratorType last)
3803  {
3804  // make sure iterator fits the current value
3805  if (JSON_HEDLEY_UNLIKELY(this != first.m_object or this != last.m_object))
3806  {
3807  JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value"));
3808  }
3809 
3810  IteratorType result = end();
3811 
3812  switch (m_type)
3813  {
3814  case value_t::boolean:
3815  case value_t::number_float:
3818  case value_t::string:
3819  {
3820  if (JSON_HEDLEY_LIKELY(not first.m_it.primitive_iterator.is_begin()
3821  or not last.m_it.primitive_iterator.is_end()))
3822  {
3823  JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
3824  }
3825 
3826  if (is_string())
3827  {
3828  AllocatorType<string_t> alloc;
3829  std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
3830  std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
3831  m_value.string = nullptr;
3832  }
3833 
3834  m_type = value_t::null;
3835  assert_invariant();
3836  break;
3837  }
3838 
3839  case value_t::object:
3840  {
3841  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3842  last.m_it.object_iterator);
3843  break;
3844  }
3845 
3846  case value_t::array:
3847  {
3848  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3849  last.m_it.array_iterator);
3850  break;
3851  }
3852 
3853  default:
3854  JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
3855  }
3856 
3857  return result;
3858  }
3859 
3889  size_type erase(const typename object_t::key_type& key)
3890  {
3891  // this erase only works for objects
3892  if (JSON_HEDLEY_LIKELY(is_object()))
3893  {
3894  return m_value.object->erase(key);
3895  }
3896 
3897  JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
3898  }
3899 
3924  void erase(const size_type idx)
3925  {
3926  // this erase only works for arrays
3927  if (JSON_HEDLEY_LIKELY(is_array()))
3928  {
3929  if (JSON_HEDLEY_UNLIKELY(idx >= size()))
3930  {
3931  JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
3932  }
3933 
3934  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
3935  }
3936  else
3937  {
3938  JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
3939  }
3940  }
3941 
3943 
3944 
3946  // lookup //
3948 
3951 
3976  template<typename KeyT>
3977  iterator find(KeyT&& key)
3978  {
3979  auto result = end();
3980 
3981  if (is_object())
3982  {
3983  result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
3984  }
3985 
3986  return result;
3987  }
3988 
3993  template<typename KeyT>
3994  const_iterator find(KeyT&& key) const
3995  {
3996  auto result = cend();
3997 
3998  if (is_object())
3999  {
4000  result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
4001  }
4002 
4003  return result;
4004  }
4005 
4027  template<typename KeyT>
4028  size_type count(KeyT&& key) const
4029  {
4030  // return 0 for all nonobject types
4031  return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
4032  }
4033 
4059  template<typename KeyT, typename std::enable_if<
4060  not std::is_same<typename std::decay<KeyT>::type, json_pointer>::value, int>::type = 0>
4061  bool contains(KeyT && key) const
4062  {
4063  return is_object() and m_value.object->find(std::forward<KeyT>(key)) != m_value.object->end();
4064  }
4065 
4092  bool contains(const json_pointer& ptr) const
4093  {
4094  return ptr.contains(this);
4095  }
4096 
4098 
4099 
4101  // iterators //
4103 
4106 
4131  iterator begin() noexcept
4132  {
4133  iterator result(this);
4134  result.set_begin();
4135  return result;
4136  }
4137 
4141  const_iterator begin() const noexcept
4142  {
4143  return cbegin();
4144  }
4145 
4171  const_iterator cbegin() const noexcept
4172  {
4173  const_iterator result(this);
4174  result.set_begin();
4175  return result;
4176  }
4177 
4202  iterator end() noexcept
4203  {
4204  iterator result(this);
4205  result.set_end();
4206  return result;
4207  }
4208 
4212  const_iterator end() const noexcept
4213  {
4214  return cend();
4215  }
4216 
4242  const_iterator cend() const noexcept
4243  {
4244  const_iterator result(this);
4245  result.set_end();
4246  return result;
4247  }
4248 
4273  {
4274  return reverse_iterator(end());
4275  }
4276 
4281  {
4282  return crbegin();
4283  }
4284 
4310  {
4311  return reverse_iterator(begin());
4312  }
4313 
4317  const_reverse_iterator rend() const noexcept
4318  {
4319  return crend();
4320  }
4321 
4347  {
4348  return const_reverse_iterator(cend());
4349  }
4350 
4376  {
4377  return const_reverse_iterator(cbegin());
4378  }
4379 
4380  public:
4438  JSON_HEDLEY_DEPRECATED(3.1.0)
4440  {
4441  return ref.items();
4442  }
4443 
4447  JSON_HEDLEY_DEPRECATED(3.1.0)
4449  {
4450  return ref.items();
4451  }
4452 
4517  {
4518  return iteration_proxy<iterator>(*this);
4519  }
4520 
4525  {
4526  return iteration_proxy<const_iterator>(*this);
4527  }
4528 
4530 
4531 
4533  // capacity //
4535 
4538 
4580  bool empty() const noexcept
4581  {
4582  switch (m_type)
4583  {
4584  case value_t::null:
4585  {
4586  // null values are empty
4587  return true;
4588  }
4589 
4590  case value_t::array:
4591  {
4592  // delegate call to array_t::empty()
4593  return m_value.array->empty();
4594  }
4595 
4596  case value_t::object:
4597  {
4598  // delegate call to object_t::empty()
4599  return m_value.object->empty();
4600  }
4601 
4602  default:
4603  {
4604  // all other types are nonempty
4605  return false;
4606  }
4607  }
4608  }
4609 
4652  size_type size() const noexcept
4653  {
4654  switch (m_type)
4655  {
4656  case value_t::null:
4657  {
4658  // null values are empty
4659  return 0;
4660  }
4661 
4662  case value_t::array:
4663  {
4664  // delegate call to array_t::size()
4665  return m_value.array->size();
4666  }
4667 
4668  case value_t::object:
4669  {
4670  // delegate call to object_t::size()
4671  return m_value.object->size();
4672  }
4673 
4674  default:
4675  {
4676  // all other types have size 1
4677  return 1;
4678  }
4679  }
4680  }
4681 
4722  size_type max_size() const noexcept
4723  {
4724  switch (m_type)
4725  {
4726  case value_t::array:
4727  {
4728  // delegate call to array_t::max_size()
4729  return m_value.array->max_size();
4730  }
4731 
4732  case value_t::object:
4733  {
4734  // delegate call to object_t::max_size()
4735  return m_value.object->max_size();
4736  }
4737 
4738  default:
4739  {
4740  // all other types have max_size() == size()
4741  return size();
4742  }
4743  }
4744  }
4745 
4747 
4748 
4750  // modifiers //
4752 
4755 
4792  void clear() noexcept
4793  {
4794  switch (m_type)
4795  {
4797  {
4798  m_value.number_integer = 0;
4799  break;
4800  }
4801 
4803  {
4804  m_value.number_unsigned = 0;
4805  break;
4806  }
4807 
4808  case value_t::number_float:
4809  {
4810  m_value.number_float = 0.0;
4811  break;
4812  }
4813 
4814  case value_t::boolean:
4815  {
4816  m_value.boolean = false;
4817  break;
4818  }
4819 
4820  case value_t::string:
4821  {
4822  m_value.string->clear();
4823  break;
4824  }
4825 
4826  case value_t::array:
4827  {
4828  m_value.array->clear();
4829  break;
4830  }
4831 
4832  case value_t::object:
4833  {
4834  m_value.object->clear();
4835  break;
4836  }
4837 
4838  default:
4839  break;
4840  }
4841  }
4842 
4863  void push_back(basic_json&& val)
4864  {
4865  // push_back only works for null objects or arrays
4866  if (JSON_HEDLEY_UNLIKELY(not(is_null() or is_array())))
4867  {
4868  JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
4869  }
4870 
4871  // transform null object into an array
4872  if (is_null())
4873  {
4874  m_type = value_t::array;
4875  m_value = value_t::array;
4876  assert_invariant();
4877  }
4878 
4879  // add element to array (move semantics)
4880  m_value.array->push_back(std::move(val));
4881  // invalidate object: mark it null so we do not call the destructor
4882  // cppcheck-suppress accessMoved
4883  val.m_type = value_t::null;
4884  }
4885 
4891  {
4892  push_back(std::move(val));
4893  return *this;
4894  }
4895 
4900  void push_back(const basic_json& val)
4901  {
4902  // push_back only works for null objects or arrays
4903  if (JSON_HEDLEY_UNLIKELY(not(is_null() or is_array())))
4904  {
4905  JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
4906  }
4907 
4908  // transform null object into an array
4909  if (is_null())
4910  {
4911  m_type = value_t::array;
4912  m_value = value_t::array;
4913  assert_invariant();
4914  }
4915 
4916  // add element to array
4917  m_value.array->push_back(val);
4918  }
4919 
4925  {
4926  push_back(val);
4927  return *this;
4928  }
4929 
4950  void push_back(const typename object_t::value_type& val)
4951  {
4952  // push_back only works for null objects or objects
4953  if (JSON_HEDLEY_UNLIKELY(not(is_null() or is_object())))
4954  {
4955  JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
4956  }
4957 
4958  // transform null object into an object
4959  if (is_null())
4960  {
4961  m_type = value_t::object;
4962  m_value = value_t::object;
4963  assert_invariant();
4964  }
4965 
4966  // add element to array
4967  m_value.object->insert(val);
4968  }
4969 
4974  reference operator+=(const typename object_t::value_type& val)
4975  {
4976  push_back(val);
4977  return *this;
4978  }
4979 
5006  {
5007  if (is_object() and init.size() == 2 and (*init.begin())->is_string())
5008  {
5009  basic_json&& key = init.begin()->moved_or_copied();
5010  push_back(typename object_t::value_type(
5011  std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
5012  }
5013  else
5014  {
5015  push_back(basic_json(init));
5016  }
5017  }
5018 
5024  {
5025  push_back(init);
5026  return *this;
5027  }
5028 
5052  template<class... Args>
5053  reference emplace_back(Args&& ... args)
5054  {
5055  // emplace_back only works for null objects or arrays
5056  if (JSON_HEDLEY_UNLIKELY(not(is_null() or is_array())))
5057  {
5058  JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name())));
5059  }
5060 
5061  // transform null object into an array
5062  if (is_null())
5063  {
5064  m_type = value_t::array;
5065  m_value = value_t::array;
5066  assert_invariant();
5067  }
5068 
5069  // add element to array (perfect forwarding)
5070 #ifdef JSON_HAS_CPP_17
5071  return m_value.array->emplace_back(std::forward<Args>(args)...);
5072 #else
5073  m_value.array->emplace_back(std::forward<Args>(args)...);
5074  return m_value.array->back();
5075 #endif
5076  }
5077 
5105  template<class... Args>
5106  std::pair<iterator, bool> emplace(Args&& ... args)
5107  {
5108  // emplace only works for null objects or arrays
5109  if (JSON_HEDLEY_UNLIKELY(not(is_null() or is_object())))
5110  {
5111  JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name())));
5112  }
5113 
5114  // transform null object into an object
5115  if (is_null())
5116  {
5117  m_type = value_t::object;
5118  m_value = value_t::object;
5119  assert_invariant();
5120  }
5121 
5122  // add element to array (perfect forwarding)
5123  auto res = m_value.object->emplace(std::forward<Args>(args)...);
5124  // create result iterator and set iterator to the result of emplace
5125  auto it = begin();
5126  it.m_it.object_iterator = res.first;
5127 
5128  // return pair of iterator and boolean
5129  return {it, res.second};
5130  }
5131 
5135  template<typename... Args>
5137  {
5138  iterator result(this);
5139  assert(m_value.array != nullptr);
5140 
5141  auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
5142  m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
5143  result.m_it.array_iterator = m_value.array->begin() + insert_pos;
5144 
5145  // This could have been written as:
5146  // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5147  // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
5148 
5149  return result;
5150  }
5151 
5175  {
5176  // insert only works for arrays
5177  if (JSON_HEDLEY_LIKELY(is_array()))
5178  {
5179  // check if iterator pos fits to this JSON value
5180  if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
5181  {
5182  JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
5183  }
5184 
5185  // insert to array and return iterator
5186  return insert_iterator(pos, val);
5187  }
5188 
5189  JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
5190  }
5191 
5197  {
5198  return insert(pos, val);
5199  }
5200 
5226  {
5227  // insert only works for arrays
5228  if (JSON_HEDLEY_LIKELY(is_array()))
5229  {
5230  // check if iterator pos fits to this JSON value
5231  if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
5232  {
5233  JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
5234  }
5235 
5236  // insert to array and return iterator
5237  return insert_iterator(pos, cnt, val);
5238  }
5239 
5240  JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
5241  }
5242 
5274  {
5275  // insert only works for arrays
5276  if (JSON_HEDLEY_UNLIKELY(not is_array()))
5277  {
5278  JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
5279  }
5280 
5281  // check if iterator pos fits to this JSON value
5282  if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
5283  {
5284  JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
5285  }
5286 
5287  // check if range iterators belong to the same JSON object
5288  if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
5289  {
5290  JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
5291  }
5292 
5293  if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
5294  {
5295  JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container"));
5296  }
5297 
5298  // insert to array and return iterator
5299  return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
5300  }
5301 
5327  {
5328  // insert only works for arrays
5329  if (JSON_HEDLEY_UNLIKELY(not is_array()))
5330  {
5331  JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
5332  }
5333 
5334  // check if iterator pos fits to this JSON value
5335  if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
5336  {
5337  JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
5338  }
5339 
5340  // insert to array and return iterator
5341  return insert_iterator(pos, ilist.begin(), ilist.end());
5342  }
5343 
5368  {
5369  // insert only works for objects
5370  if (JSON_HEDLEY_UNLIKELY(not is_object()))
5371  {
5372  JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
5373  }
5374 
5375  // check if range iterators belong to the same JSON object
5376  if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
5377  {
5378  JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
5379  }
5380 
5381  // passed iterators must belong to objects
5382  if (JSON_HEDLEY_UNLIKELY(not first.m_object->is_object()))
5383  {
5384  JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
5385  }
5386 
5387  m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
5388  }
5389 
5410  {
5411  // implicitly convert null value to an empty object
5412  if (is_null())
5413  {
5414  m_type = value_t::object;
5415  m_value.object = create<object_t>();
5416  assert_invariant();
5417  }
5418 
5419  if (JSON_HEDLEY_UNLIKELY(not is_object()))
5420  {
5421  JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
5422  }
5423  if (JSON_HEDLEY_UNLIKELY(not j.is_object()))
5424  {
5425  JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name())));
5426  }
5427 
5428  for (auto it = j.cbegin(); it != j.cend(); ++it)
5429  {
5430  m_value.object->operator[](it.key()) = it.value();
5431  }
5432  }
5433 
5461  {
5462  // implicitly convert null value to an empty object
5463  if (is_null())
5464  {
5465  m_type = value_t::object;
5466  m_value.object = create<object_t>();
5467  assert_invariant();
5468  }
5469 
5470  if (JSON_HEDLEY_UNLIKELY(not is_object()))
5471  {
5472  JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
5473  }
5474 
5475  // check if range iterators belong to the same JSON object
5476  if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
5477  {
5478  JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
5479  }
5480 
5481  // passed iterators must belong to objects
5482  if (JSON_HEDLEY_UNLIKELY(not first.m_object->is_object()
5483  or not last.m_object->is_object()))
5484  {
5485  JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
5486  }
5487 
5488  for (auto it = first; it != last; ++it)
5489  {
5490  m_value.object->operator[](it.key()) = it.value();
5491  }
5492  }
5493 
5511  void swap(reference other) noexcept (
5512  std::is_nothrow_move_constructible<value_t>::value and
5513  std::is_nothrow_move_assignable<value_t>::value and
5514  std::is_nothrow_move_constructible<json_value>::value and
5515  std::is_nothrow_move_assignable<json_value>::value
5516  )
5517  {
5518  std::swap(m_type, other.m_type);
5519  std::swap(m_value, other.m_value);
5520  assert_invariant();
5521  }
5522 
5543  void swap(array_t& other)
5544  {
5545  // swap only works for arrays
5546  if (JSON_HEDLEY_LIKELY(is_array()))
5547  {
5548  std::swap(*(m_value.array), other);
5549  }
5550  else
5551  {
5552  JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
5553  }
5554  }
5555 
5576  void swap(object_t& other)
5577  {
5578  // swap only works for objects
5579  if (JSON_HEDLEY_LIKELY(is_object()))
5580  {
5581  std::swap(*(m_value.object), other);
5582  }
5583  else
5584  {
5585  JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
5586  }
5587  }
5588 
5609  void swap(string_t& other)
5610  {
5611  // swap only works for strings
5612  if (JSON_HEDLEY_LIKELY(is_string()))
5613  {
5614  std::swap(*(m_value.string), other);
5615  }
5616  else
5617  {
5618  JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
5619  }
5620  }
5621 
5623 
5624  public:
5626  // lexicographical comparison operators //
5628 
5631 
5671  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5672  {
5673  const auto lhs_type = lhs.type();
5674  const auto rhs_type = rhs.type();
5675 
5676  if (lhs_type == rhs_type)
5677  {
5678  switch (lhs_type)
5679  {
5680  case value_t::array:
5681  return *lhs.m_value.array == *rhs.m_value.array;
5682 
5683  case value_t::object:
5684  return *lhs.m_value.object == *rhs.m_value.object;
5685 
5686  case value_t::null:
5687  return true;
5688 
5689  case value_t::string:
5690  return *lhs.m_value.string == *rhs.m_value.string;
5691 
5692  case value_t::boolean:
5693  return lhs.m_value.boolean == rhs.m_value.boolean;
5694 
5696  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5697 
5699  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5700 
5701  case value_t::number_float:
5702  return lhs.m_value.number_float == rhs.m_value.number_float;
5703 
5704  default:
5705  return false;
5706  }
5707  }
5708  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5709  {
5710  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5711  }
5712  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5713  {
5714  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5715  }
5716  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5717  {
5718  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5719  }
5720  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5721  {
5722  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5723  }
5724  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5725  {
5726  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5727  }
5728  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5729  {
5730  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5731  }
5732 
5733  return false;
5734  }
5735 
5740  template<typename ScalarType, typename std::enable_if<
5741  std::is_scalar<ScalarType>::value, int>::type = 0>
5742  friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
5743  {
5744  return lhs == basic_json(rhs);
5745  }
5746 
5751  template<typename ScalarType, typename std::enable_if<
5752  std::is_scalar<ScalarType>::value, int>::type = 0>
5753  friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
5754  {
5755  return basic_json(lhs) == rhs;
5756  }
5757 
5776  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5777  {
5778  return not (lhs == rhs);
5779  }
5780 
5785  template<typename ScalarType, typename std::enable_if<
5786  std::is_scalar<ScalarType>::value, int>::type = 0>
5787  friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
5788  {
5789  return lhs != basic_json(rhs);
5790  }
5791 
5796  template<typename ScalarType, typename std::enable_if<
5797  std::is_scalar<ScalarType>::value, int>::type = 0>
5798  friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
5799  {
5800  return basic_json(lhs) != rhs;
5801  }
5802 
5829  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5830  {
5831  const auto lhs_type = lhs.type();
5832  const auto rhs_type = rhs.type();
5833 
5834  if (lhs_type == rhs_type)
5835  {
5836  switch (lhs_type)
5837  {
5838  case value_t::array:
5839  // note parentheses are necessary, see
5840  // https://github.com/nlohmann/json/issues/1530
5841  return (*lhs.m_value.array) < (*rhs.m_value.array);
5842 
5843  case value_t::object:
5844  return (*lhs.m_value.object) < (*rhs.m_value.object);
5845 
5846  case value_t::null:
5847  return false;
5848 
5849  case value_t::string:
5850  return (*lhs.m_value.string) < (*rhs.m_value.string);
5851 
5852  case value_t::boolean:
5853  return (lhs.m_value.boolean) < (rhs.m_value.boolean);
5854 
5856  return (lhs.m_value.number_integer) < (rhs.m_value.number_integer);
5857 
5859  return (lhs.m_value.number_unsigned) < (rhs.m_value.number_unsigned);
5860 
5861  case value_t::number_float:
5862  return (lhs.m_value.number_float) < (rhs.m_value.number_float);
5863 
5864  default:
5865  return false;
5866  }
5867  }
5868  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5869  {
5870  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5871  }
5872  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5873  {
5874  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
5875  }
5876  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5877  {
5878  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5879  }
5880  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5881  {
5882  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
5883  }
5884  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5885  {
5886  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5887  }
5888  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5889  {
5890  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5891  }
5892 
5893  // We only reach this line if we cannot compare values. In that case,
5894  // we compare types. Note we have to call the operator explicitly,
5895  // because MSVC has problems otherwise.
5896  return operator<(lhs_type, rhs_type);
5897  }
5898 
5903  template<typename ScalarType, typename std::enable_if<
5904  std::is_scalar<ScalarType>::value, int>::type = 0>
5905  friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
5906  {
5907  return lhs < basic_json(rhs);
5908  }
5909 
5914  template<typename ScalarType, typename std::enable_if<
5915  std::is_scalar<ScalarType>::value, int>::type = 0>
5916  friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
5917  {
5918  return basic_json(lhs) < rhs;
5919  }
5920 
5940  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5941  {
5942  return not (rhs < lhs);
5943  }
5944 
5949  template<typename ScalarType, typename std::enable_if<
5950  std::is_scalar<ScalarType>::value, int>::type = 0>
5951  friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
5952  {
5953  return lhs <= basic_json(rhs);
5954  }
5955 
5960  template<typename ScalarType, typename std::enable_if<
5961  std::is_scalar<ScalarType>::value, int>::type = 0>
5962  friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
5963  {
5964  return basic_json(lhs) <= rhs;
5965  }
5966 
5986  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5987  {
5988  return not (lhs <= rhs);
5989  }
5990 
5995  template<typename ScalarType, typename std::enable_if<
5996  std::is_scalar<ScalarType>::value, int>::type = 0>
5997  friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
5998  {
5999  return lhs > basic_json(rhs);
6000  }
6001 
6006  template<typename ScalarType, typename std::enable_if<
6007  std::is_scalar<ScalarType>::value, int>::type = 0>
6008  friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
6009  {
6010  return basic_json(lhs) > rhs;
6011  }
6012 
6032  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
6033  {
6034  return not (lhs < rhs);
6035  }
6036 
6041  template<typename ScalarType, typename std::enable_if<
6042  std::is_scalar<ScalarType>::value, int>::type = 0>
6043  friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
6044  {
6045  return lhs >= basic_json(rhs);
6046  }
6047 
6052  template<typename ScalarType, typename std::enable_if<
6053  std::is_scalar<ScalarType>::value, int>::type = 0>
6054  friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
6055  {
6056  return basic_json(lhs) >= rhs;
6057  }
6058 
6060 
6062  // serialization //
6064 
6067 
6099  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
6100  {
6101  // read width member and use it as indentation parameter if nonzero
6102  const bool pretty_print = o.width() > 0;
6103  const auto indentation = pretty_print ? o.width() : 0;
6104 
6105  // reset width to 0 for subsequent calls to this stream
6106  o.width(0);
6107 
6108  // do the actual serialization
6109  serializer s(detail::output_adapter<char>(o), o.fill());
6110  s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
6111  return o;
6112  }
6113 
6122  JSON_HEDLEY_DEPRECATED(3.0.0)
6123  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
6124  {
6125  return o << j;
6126  }
6127 
6129 
6130 
6132  // deserialization //
6134 
6137 
6201  JSON_HEDLEY_WARN_UNUSED_RESULT
6203  const parser_callback_t cb = nullptr,
6204  const bool allow_exceptions = true)
6205  {
6206  basic_json result;
6207  parser(i, cb, allow_exceptions).parse(true, result);
6208  return result;
6209  }
6210 
6211  static bool accept(detail::input_adapter&& i)
6212  {
6213  return parser(i).accept(true);
6214  }
6215 
6269  template <typename SAX>
6270  JSON_HEDLEY_NON_NULL(2)
6271  static bool sax_parse(detail::input_adapter&& i, SAX* sax,
6273  const bool strict = true)
6274  {
6275  assert(sax);
6276  return format == input_format_t::json
6277  ? parser(std::move(i)).sax_parse(sax, strict)
6278  : detail::binary_reader<basic_json, SAX>(std::move(i)).sax_parse(format, sax, strict);
6279  }
6280 
6330  template<class IteratorType, typename std::enable_if<
6331  std::is_base_of<
6332  std::random_access_iterator_tag,
6333  typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
6334  static basic_json parse(IteratorType first, IteratorType last,
6335  const parser_callback_t cb = nullptr,
6336  const bool allow_exceptions = true)
6337  {
6338  basic_json result;
6339  parser(detail::input_adapter(first, last), cb, allow_exceptions).parse(true, result);
6340  return result;
6341  }
6342 
6343  template<class IteratorType, typename std::enable_if<
6344  std::is_base_of<
6345  std::random_access_iterator_tag,
6346  typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
6347  static bool accept(IteratorType first, IteratorType last)
6348  {
6349  return parser(detail::input_adapter(first, last)).accept(true);
6350  }
6351 
6352  template<class IteratorType, class SAX, typename std::enable_if<
6353  std::is_base_of<
6354  std::random_access_iterator_tag,
6355  typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
6356  JSON_HEDLEY_NON_NULL(3)
6357  static bool sax_parse(IteratorType first, IteratorType last, SAX* sax)
6358  {
6359  return parser(detail::input_adapter(first, last)).sax_parse(sax);
6360  }
6361 
6370  JSON_HEDLEY_DEPRECATED(3.0.0)
6371  friend std::istream& operator<<(basic_json& j, std::istream& i)
6372  {
6373  return operator>>(i, j);
6374  }
6375 
6401  friend std::istream& operator>>(std::istream& i, basic_json& j)
6402  {
6403  parser(detail::input_adapter(i)).parse(false, j);
6404  return i;
6405  }
6406 
6408 
6410  // convenience functions //
6412 
6443  JSON_HEDLEY_RETURNS_NON_NULL
6444  const char* type_name() const noexcept
6445  {
6446  {
6447  switch (m_type)
6448  {
6449  case value_t::null:
6450  return "null";
6451  case value_t::object:
6452  return "object";
6453  case value_t::array:
6454  return "array";
6455  case value_t::string:
6456  return "string";
6457  case value_t::boolean:
6458  return "boolean";
6459  case value_t::discarded:
6460  return "discarded";
6461  default:
6462  return "number";
6463  }
6464  }
6465  }
6466 
6467 
6468  private:
6470  // member variables //
6472 
6474  value_t m_type = value_t::null;
6475 
6477  json_value m_value = {};
6478 
6480  // binary serialization/deserialization //
6482 
6485 
6486  public:
6575  static std::vector<uint8_t> to_cbor(const basic_json& j)
6576  {
6577  std::vector<uint8_t> result;
6578  to_cbor(j, result);
6579  return result;
6580  }
6581 
6582  static void to_cbor(const basic_json& j, detail::output_adapter<uint8_t> o)
6583  {
6584  binary_writer<uint8_t>(o).write_cbor(j);
6585  }
6586 
6587  static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
6588  {
6589  binary_writer<char>(o).write_cbor(j);
6590  }
6591 
6671  static std::vector<uint8_t> to_msgpack(const basic_json& j)
6672  {
6673  std::vector<uint8_t> result;
6674  to_msgpack(j, result);
6675  return result;
6676  }
6677 
6678  static void to_msgpack(const basic_json& j, detail::output_adapter<uint8_t> o)
6679  {
6680  binary_writer<uint8_t>(o).write_msgpack(j);
6681  }
6682 
6683  static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
6684  {
6685  binary_writer<char>(o).write_msgpack(j);
6686  }
6687 
6768  static std::vector<uint8_t> to_ubjson(const basic_json& j,
6769  const bool use_size = false,
6770  const bool use_type = false)
6771  {
6772  std::vector<uint8_t> result;
6773  to_ubjson(j, result, use_size, use_type);
6774  return result;
6775  }
6776 
6777  static void to_ubjson(const basic_json& j, detail::output_adapter<uint8_t> o,
6778  const bool use_size = false, const bool use_type = false)
6779  {
6780  binary_writer<uint8_t>(o).write_ubjson(j, use_size, use_type);
6781  }
6782 
6783  static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
6784  const bool use_size = false, const bool use_type = false)
6785  {
6786  binary_writer<char>(o).write_ubjson(j, use_size, use_type);
6787  }
6788 
6789 
6845  static std::vector<uint8_t> to_bson(const basic_json& j)
6846  {
6847  std::vector<uint8_t> result;
6848  to_bson(j, result);
6849  return result;
6850  }
6851 
6861  {
6863  }
6864 
6869  {
6871  }
6872 
6873 
6973  JSON_HEDLEY_WARN_UNUSED_RESULT
6975  const bool strict = true,
6976  const bool allow_exceptions = true)
6977  {
6978  basic_json result;
6979  detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
6980  const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::cbor, &sdp, strict);
6981  return res ? result : basic_json(value_t::discarded);
6982  }
6983 
6987  template<typename A1, typename A2,
6988  detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
6989  JSON_HEDLEY_WARN_UNUSED_RESULT
6990  static basic_json from_cbor(A1 && a1, A2 && a2,
6991  const bool strict = true,
6992  const bool allow_exceptions = true)
6993  {
6994  basic_json result;
6995  detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
6996  const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::cbor, &sdp, strict);
6997  return res ? result : basic_json(value_t::discarded);
6998  }
6999 
7082  JSON_HEDLEY_WARN_UNUSED_RESULT
7084  const bool strict = true,
7085  const bool allow_exceptions = true)
7086  {
7087  basic_json result;
7088  detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
7089  const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::msgpack, &sdp, strict);
7090  return res ? result : basic_json(value_t::discarded);
7091  }
7092 
7096  template<typename A1, typename A2,
7097  detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
7098  JSON_HEDLEY_WARN_UNUSED_RESULT
7099  static basic_json from_msgpack(A1 && a1, A2 && a2,
7100  const bool strict = true,
7101  const bool allow_exceptions = true)
7102  {
7103  basic_json result;
7104  detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
7105  const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::msgpack, &sdp, strict);
7106  return res ? result : basic_json(value_t::discarded);
7107  }
7108 
7170  JSON_HEDLEY_WARN_UNUSED_RESULT
7172  const bool strict = true,
7173  const bool allow_exceptions = true)
7174  {
7175  basic_json result;
7176  detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
7177  const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::ubjson, &sdp, strict);
7178  return res ? result : basic_json(value_t::discarded);
7179  }
7180 
7184  template<typename A1, typename A2,
7185  detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
7186  JSON_HEDLEY_WARN_UNUSED_RESULT
7187  static basic_json from_ubjson(A1 && a1, A2 && a2,
7188  const bool strict = true,
7189  const bool allow_exceptions = true)
7190  {
7191  basic_json result;
7192  detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
7193  const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::ubjson, &sdp, strict);
7194  return res ? result : basic_json(value_t::discarded);
7195  }
7196 
7257  JSON_HEDLEY_WARN_UNUSED_RESULT
7259  const bool strict = true,
7260  const bool allow_exceptions = true)
7261  {
7262  basic_json result;
7263  detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
7264  const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::bson, &sdp, strict);
7265  return res ? result : basic_json(value_t::discarded);
7266  }
7267 
7271  template<typename A1, typename A2,
7272  detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
7273  JSON_HEDLEY_WARN_UNUSED_RESULT
7274  static basic_json from_bson(A1 && a1, A2 && a2,
7275  const bool strict = true,
7276  const bool allow_exceptions = true)
7277  {
7278  basic_json result;
7279  detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
7280  const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::bson, &sdp, strict);
7281  return res ? result : basic_json(value_t::discarded);
7282  }
7283 
7284 
7285 
7287 
7289  // JSON Pointer support //
7291 
7294 
7329  {
7330  return ptr.get_unchecked(this);
7331  }
7332 
7357  {
7358  return ptr.get_unchecked(this);
7359  }
7360 
7400  {
7401  return ptr.get_checked(this);
7402  }
7403 
7442  const_reference at(const json_pointer& ptr) const
7443  {
7444  return ptr.get_checked(this);
7445  }
7446 
7470  {
7471  basic_json result(value_t::object);
7472  json_pointer::flatten("", *this, result);
7473  return result;
7474  }
7475 
7507  {
7508  return json_pointer::unflatten(*this);
7509  }
7510 
7512 
7514  // JSON Patch functions //
7516 
7519 
7567  basic_json patch(const basic_json& json_patch) const
7568  {
7569  // make a working copy to apply the patch to
7570  basic_json result = *this;
7571 
7572  // the valid JSON Patch operations
7573  enum class patch_operations {add, remove, replace, move, copy, test, invalid};
7574 
7575  const auto get_op = [](const std::string & op)
7576  {
7577  if (op == "add")
7578  {
7579  return patch_operations::add;
7580  }
7581  if (op == "remove")
7582  {
7583  return patch_operations::remove;
7584  }
7585  if (op == "replace")
7586  {
7587  return patch_operations::replace;
7588  }
7589  if (op == "move")
7590  {
7591  return patch_operations::move;
7592  }
7593  if (op == "copy")
7594  {
7595  return patch_operations::copy;
7596  }
7597  if (op == "test")
7598  {
7599  return patch_operations::test;
7600  }
7601 
7602  return patch_operations::invalid;
7603  };
7604 
7605  // wrapper for "add" operation; add value at ptr
7606  const auto operation_add = [&result](json_pointer & ptr, basic_json val)
7607  {
7608  // adding to the root of the target document means replacing it
7609  if (ptr.empty())
7610  {
7611  result = val;
7612  return;
7613  }
7614 
7615  // make sure the top element of the pointer exists
7616  json_pointer top_pointer = ptr.top();
7617  if (top_pointer != ptr)
7618  {
7619  result.at(top_pointer);
7620  }
7621 
7622  // get reference to parent of JSON pointer ptr
7623  const auto last_path = ptr.back();
7624  ptr.pop_back();
7625  basic_json& parent = result[ptr];
7626 
7627  switch (parent.m_type)
7628  {
7629  case value_t::null:
7630  case value_t::object:
7631  {
7632  // use operator[] to add value
7633  parent[last_path] = val;
7634  break;
7635  }
7636 
7637  case value_t::array:
7638  {
7639  if (last_path == "-")
7640  {
7641  // special case: append to back
7642  parent.push_back(val);
7643  }
7644  else
7645  {
7646  const auto idx = json_pointer::array_index(last_path);
7647  if (JSON_HEDLEY_UNLIKELY(static_cast<size_type>(idx) > parent.size()))
7648  {
7649  // avoid undefined behavior
7650  JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
7651  }
7652 
7653  // default case: insert add offset
7654  parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
7655  }
7656  break;
7657  }
7658 
7659  // if there exists a parent it cannot be primitive
7660  default: // LCOV_EXCL_LINE
7661  assert(false); // LCOV_EXCL_LINE
7662  }
7663  };
7664 
7665  // wrapper for "remove" operation; remove value at ptr
7666  const auto operation_remove = [&result](json_pointer & ptr)
7667  {
7668  // get reference to parent of JSON pointer ptr
7669  const auto last_path = ptr.back();
7670  ptr.pop_back();
7671  basic_json& parent = result.at(ptr);
7672 
7673  // remove child
7674  if (parent.is_object())
7675  {
7676  // perform range check
7677  auto it = parent.find(last_path);
7678  if (JSON_HEDLEY_LIKELY(it != parent.end()))
7679  {
7680  parent.erase(it);
7681  }
7682  else
7683  {
7684  JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found"));
7685  }
7686  }
7687  else if (parent.is_array())
7688  {
7689  // note erase performs range check
7690  parent.erase(static_cast<size_type>(json_pointer::array_index(last_path)));
7691  }
7692  };
7693 
7694  // type check: top level value must be an array
7695  if (JSON_HEDLEY_UNLIKELY(not json_patch.is_array()))
7696  {
7697  JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
7698  }
7699 
7700  // iterate and apply the operations
7701  for (const auto& val : json_patch)
7702  {
7703  // wrapper to get a value for an operation
7704  const auto get_value = [&val](const std::string & op,
7705  const std::string & member,
7706  bool string_type) -> basic_json &
7707  {
7708  // find value
7709  auto it = val.m_value.object->find(member);
7710 
7711  // context-sensitive error message
7712  const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
7713 
7714  // check if desired value is present
7715  if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end()))
7716  {
7717  JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'"));
7718  }
7719 
7720  // check if result is of type string
7721  if (JSON_HEDLEY_UNLIKELY(string_type and not it->second.is_string()))
7722  {
7723  JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'"));
7724  }
7725 
7726  // no error: return value
7727  return it->second;
7728  };
7729 
7730  // type check: every element of the array must be an object
7731  if (JSON_HEDLEY_UNLIKELY(not val.is_object()))
7732  {
7733  JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
7734  }
7735 
7736  // collect mandatory members
7737  const std::string op = get_value("op", "op", true);
7738  const std::string path = get_value(op, "path", true);
7739  json_pointer ptr(path);
7740 
7741  switch (get_op(op))
7742  {
7743  case patch_operations::add:
7744  {
7745  operation_add(ptr, get_value("add", "value", false));
7746  break;
7747  }
7748 
7749  case patch_operations::remove:
7750  {
7751  operation_remove(ptr);
7752  break;
7753  }
7754 
7755  case patch_operations::replace:
7756  {
7757  // the "path" location must exist - use at()
7758  result.at(ptr) = get_value("replace", "value", false);
7759  break;
7760  }
7761 
7762  case patch_operations::move:
7763  {
7764  const std::string from_path = get_value("move", "from", true);
7765  json_pointer from_ptr(from_path);
7766 
7767  // the "from" location must exist - use at()
7768  basic_json v = result.at(from_ptr);
7769 
7770  // The move operation is functionally identical to a
7771  // "remove" operation on the "from" location, followed
7772  // immediately by an "add" operation at the target
7773  // location with the value that was just removed.
7774  operation_remove(from_ptr);
7775  operation_add(ptr, v);
7776  break;
7777  }
7778 
7779  case patch_operations::copy:
7780  {
7781  const std::string from_path = get_value("copy", "from", true);
7782  const json_pointer from_ptr(from_path);
7783 
7784  // the "from" location must exist - use at()
7785  basic_json v = result.at(from_ptr);
7786 
7787  // The copy is functionally identical to an "add"
7788  // operation at the target location using the value
7789  // specified in the "from" member.
7790  operation_add(ptr, v);
7791  break;
7792  }
7793 
7794  case patch_operations::test:
7795  {
7796  bool success = false;
7797  JSON_TRY
7798  {
7799  // check if "value" matches the one at "path"
7800  // the "path" location must exist - use at()
7801  success = (result.at(ptr) == get_value("test", "value", false));
7802  }
7803  JSON_INTERNAL_CATCH (out_of_range&)
7804  {
7805  // ignore out of range errors: success remains false
7806  }
7807 
7808  // throw an exception if test fails
7809  if (JSON_HEDLEY_UNLIKELY(not success))
7810  {
7811  JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump()));
7812  }
7813 
7814  break;
7815  }
7816 
7817  default:
7818  {
7819  // op must be "add", "remove", "replace", "move", "copy", or
7820  // "test"
7821  JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid"));
7822  }
7823  }
7824  }
7825 
7826  return result;
7827  }
7828 
7862  JSON_HEDLEY_WARN_UNUSED_RESULT
7863  static basic_json diff(const basic_json& source, const basic_json& target,
7864  const std::string& path = "")
7865  {
7866  // the patch
7867  basic_json result(value_t::array);
7868 
7869  // if the values are the same, return empty patch
7870  if (source == target)
7871  {
7872  return result;
7873  }
7874 
7875  if (source.type() != target.type())
7876  {
7877  // different types: replace value
7878  result.push_back(
7879  {
7880  {"op", "replace"}, {"path", path}, {"value", target}
7881  });
7882  return result;
7883  }
7884 
7885  switch (source.type())
7886  {
7887  case value_t::array:
7888  {
7889  // first pass: traverse common elements
7890  std::size_t i = 0;
7891  while (i < source.size() and i < target.size())
7892  {
7893  // recursive call to compare array values at index i
7894  auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
7895  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
7896  ++i;
7897  }
7898 
7899  // i now reached the end of at least one array
7900  // in a second pass, traverse the remaining elements
7901 
7902  // remove my remaining elements
7903  const auto end_index = static_cast<difference_type>(result.size());
7904  while (i < source.size())
7905  {
7906  // add operations in reverse order to avoid invalid
7907  // indices
7908  result.insert(result.begin() + end_index, object(
7909  {
7910  {"op", "remove"},
7911  {"path", path + "/" + std::to_string(i)}
7912  }));
7913  ++i;
7914  }
7915 
7916  // add other remaining elements
7917  while (i < target.size())
7918  {
7919  result.push_back(
7920  {
7921  {"op", "add"},
7922  {"path", path + "/" + std::to_string(i)},
7923  {"value", target[i]}
7924  });
7925  ++i;
7926  }
7927 
7928  break;
7929  }
7930 
7931  case value_t::object:
7932  {
7933  // first pass: traverse this object's elements
7934  for (auto it = source.cbegin(); it != source.cend(); ++it)
7935  {
7936  // escape the key name to be used in a JSON patch
7937  const auto key = json_pointer::escape(it.key());
7938 
7939  if (target.find(it.key()) != target.end())
7940  {
7941  // recursive call to compare object values at key it
7942  auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
7943  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
7944  }
7945  else
7946  {
7947  // found a key that is not in o -> remove it
7948  result.push_back(object(
7949  {
7950  {"op", "remove"}, {"path", path + "/" + key}
7951  }));
7952  }
7953  }
7954 
7955  // second pass: traverse other object's elements
7956  for (auto it = target.cbegin(); it != target.cend(); ++it)
7957  {
7958  if (source.find(it.key()) == source.end())
7959  {
7960  // found a key that is not in this -> add it
7961  const auto key = json_pointer::escape(it.key());
7962  result.push_back(
7963  {
7964  {"op", "add"}, {"path", path + "/" + key},
7965  {"value", it.value()}
7966  });
7967  }
7968  }
7969 
7970  break;
7971  }
7972 
7973  default:
7974  {
7975  // both primitive type: replace value
7976  result.push_back(
7977  {
7978  {"op", "replace"}, {"path", path}, {"value", target}
7979  });
7980  break;
7981  }
7982  }
7983 
7984  return result;
7985  }
7986 
7988 
7990  // JSON Merge Patch functions //
7992 
7995 
8038  void merge_patch(const basic_json& apply_patch)
8039  {
8040  if (apply_patch.is_object())
8041  {
8042  if (not is_object())
8043  {
8044  *this = object();
8045  }
8046  for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
8047  {
8048  if (it.value().is_null())
8049  {
8050  erase(it.key());
8051  }
8052  else
8053  {
8054  operator[](it.key()).merge_patch(it.value());
8055  }
8056  }
8057  }
8058  else
8059  {
8060  *this = apply_patch;
8061  }
8062  }
8063 
8065 };
8066 
8076 NLOHMANN_BASIC_JSON_TPL_DECLARATION
8077 std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
8078 {
8079  return j.dump();
8080 }
8081 } // namespace nlohmann
8082 
8084 // nonmember support //
8086 
8087 // specialization of std::swap, and std::hash
8088 namespace std
8089 {
8090 
8092 template<>
8093 struct hash<nlohmann::json>
8094 {
8100  std::size_t operator()(const nlohmann::json& j) const
8101  {
8102  // a naive hashing via the string representation
8103  const auto& h = hash<nlohmann::json::string_t>();
8104  return h(j.dump());
8105  }
8106 };
8107 
8111 template<>
8112 struct less<::nlohmann::detail::value_t>
8113 {
8119  nlohmann::detail::value_t rhs) const noexcept
8120  {
8121  return nlohmann::detail::operator<(lhs, rhs);
8122  }
8123 };
8124 
8130 template<>
8131 inline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept(
8132  is_nothrow_move_constructible<nlohmann::json>::value and
8133  is_nothrow_move_assignable<nlohmann::json>::value
8134 )
8135 {
8136  j1.swap(j2);
8137 }
8138 
8139 } // namespace std
8140 
8154 JSON_HEDLEY_NON_NULL(1)
8155 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
8156 {
8157  return nlohmann::json::parse(s, s + n);
8158 }
8159 
8173 JSON_HEDLEY_NON_NULL(1)
8174 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
8175 {
8176  return nlohmann::json::json_pointer(std::string(s, n));
8177 }
8178 
8179 #include <nlohmann/detail/macro_unscope.hpp>
8180 
8181 #endif // INCLUDE_NLOHMANN_JSON_HPP_
nlohmann::detail::json_reverse_iterator
a template for a reverse iterator class
Definition: json_reverse_iterator.hpp:35
nlohmann::basic_json::insert
void insert(const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:5367
nlohmann::basic_json::erase
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition: json.hpp:3697
nlohmann::basic_json::number_float_t
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:819
nlohmann::detail::type_error
exception indicating executing a member function with a wrong type
Definition: exceptions.hpp:258
nlohmann::basic_json::operator[]
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition: json.hpp:7356
nlohmann::basic_json::insert
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:5225
nlohmann::to_string
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:8077
nlohmann::detail::exception
general exception of the basic_json class
Definition: exceptions.hpp:47
nlohmann::json_pointer::empty
bool empty() const noexcept
return whether pointer points to the root document
Definition: json_pointer.hpp:317
nlohmann::detail::has_from_json
Definition: type_traits.hpp:83
nlohmann::detail::value_t
value_t
the JSON type enumeration
Definition: value_t.hpp:42
nlohmann::basic_json::at
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:3023
nlohmann::basic_json::is_number_integer
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2229
nlohmann::basic_json::front
reference front()
access the first element
Definition: json.hpp:3586
nlohmann::basic_json::to_bson
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:6868
nlohmann::basic_json::array_t
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
Definition: json.hpp:529
nlohmann::basic_json::basic_json
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:1456
nlohmann::basic_json::operator!=
friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5798
nlohmann::basic_json::operator<
friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
comparison: less than
Definition: json.hpp:5905
nlohmann::detail::value_t::null
@ null
null value
nlohmann::detail::value_t::object
@ object
object (unordered set of name/value pairs)
nlohmann::basic_json::object
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json object(initializer_list_t init={})
explicitly create an object from an initializer list
Definition: json.hpp:1590
nlohmann::detail::serializer::dump
void dump(const BasicJsonType &val, const bool pretty_print, const bool ensure_ascii, const unsigned int indent_step, const unsigned int current_indent=0)
internal implementation of the serialization function
Definition: serializer.hpp:92
nlohmann::basic_json::to_msgpack
static std::vector< uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition: json.hpp:6671
nlohmann::basic_json::operator[]
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition: json.hpp:7328
nlohmann::basic_json::find
const_iterator find(KeyT &&key) const
find an element in a JSON object
Definition: json.hpp:3994
nlohmann::basic_json::basic_json
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:1889
nlohmann::basic_json::count
size_type count(KeyT &&key) const
returns the number of occurrences of a key in a JSON object
Definition: json.hpp:4028
nlohmann::basic_json::cend
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4242
nlohmann::basic_json::operator+=
reference operator+=(initializer_list_t init)
add an object to an object
Definition: json.hpp:5023
nlohmann::basic_json::begin
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4141
nlohmann::basic_json::is_null
constexpr bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2148
nlohmann::detail::out_of_range
exception indicating access out of the defined range
Definition: exceptions.hpp:305
nlohmann::basic_json::at
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition: json.hpp:7442
nlohmann::detail::invalid_iterator
exception indicating errors with iterators
Definition: exceptions.hpp:204
nlohmann::basic_json::swap
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition: json.hpp:5511
nlohmann::basic_json::reverse_iterator
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
Definition: json.hpp:281
nlohmann::basic_json::erase
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:3889
nlohmann::basic_json::from_ubjson
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(detail::input_adapter &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition: json.hpp:7171
nlohmann::basic_json::get_to
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:2728
nlohmann::detail::internal_iterator::object_iterator
BasicJsonType::object_t::iterator object_iterator
iterator for JSON objects
Definition: internal_iterator.hpp:18
nlohmann::basic_json::operator[]
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:3171
nlohmann::basic_json::size_type
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:266
nlohmann::basic_json::get
ValueType get() const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), std::declval< ValueType & >())))
get a value (explicit)
Definition: json.hpp:2631
nlohmann::basic_json::basic_json
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1682
nlohmann
namespace for Niels Lohmann
Definition: adl_serializer.hpp:9
nlohmann::detail::binary_writer
serialization to CBOR and MessagePack values
Definition: binary_writer.hpp:27
nlohmann::basic_json::array
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json array(initializer_list_t init={})
explicitly create an array from an initializer list
Definition: json.hpp:1546
nlohmann::basic_json::get
ValueType get() const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >())))
get a value (explicit); special case
Definition: json.hpp:2682
nlohmann::basic_json::swap
void swap(object_t &other)
exchanges the values
Definition: json.hpp:5576
nlohmann::basic_json::operator=
basic_json & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value)
copy assignment
Definition: json.hpp:1926
nlohmann::basic_json::is_primitive
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:2099
nlohmann::basic_json::merge_patch
void merge_patch(const basic_json &apply_patch)
applies a JSON Merge Patch
Definition: json.hpp:8038
nlohmann::detail::json_sax_dom_parser
SAX implementation to create a JSON value from SAX events.
Definition: json_sax.hpp:146
nlohmann::detail::value_t::number_float
@ number_float
number value (floating-point)
nlohmann::basic_json::find
iterator find(KeyT &&key)
find an element in a JSON object
Definition: json.hpp:3977
nlohmann::json_pointer
JSON Pointer.
Definition: json_pointer.hpp:19
nlohmann::detail::other_error
exception indicating other library errors
Definition: exceptions.hpp:343
nlohmann::basic_json::boolean_t
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:608
nlohmann::basic_json::from_msgpack
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(A1 &&a1, A2 &&a2, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition: json.hpp:7099
nlohmann::detail::value_t::number_integer
@ number_integer
number value (signed integer)
nlohmann::basic_json::update
void update(const_reference j)
updates a JSON object from another object, overwriting existing keys
Definition: json.hpp:5409
nlohmann::basic_json::operator<=
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5940
nlohmann::basic_json::update
void update(const_iterator first, const_iterator last)
updates a JSON object from another object, overwriting existing keys
Definition: json.hpp:5460
nlohmann::basic_json::is_boolean
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2170
nlohmann::basic_json::items
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
Definition: json.hpp:4524
nlohmann::basic_json::begin
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:4131
nlohmann::basic_json::push_back
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4900
nlohmann::basic_json::difference_type
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:264
nlohmann::basic_json::rend
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4317
nlohmann::basic_json::empty
bool empty() const noexcept
checks whether the container is empty.
Definition: json.hpp:4580
nlohmann::detail::lexer
lexical analysis
Definition: lexer.hpp:32
nlohmann::basic_json::get
BasicJsonType get() const
get special-case overload
Definition: json.hpp:2581
nlohmann::basic_json::object_t
ObjectType< StringType, basic_json, object_comparator_t, AllocatorType< std::pair< const StringType, basic_json > >> object_t
a type for an object
Definition: json.hpp:483
nlohmann::json_pointer::back
const std::string & back() const
return last reference token
Definition: json_pointer.hpp:270
nlohmann::detail::json_ref
Definition: json_ref.hpp:14
nlohmann::basic_json::basic_json
basic_json(CompatibleType &&val) noexcept(noexcept(JSONSerializer< U >::to_json(std::declval< basic_json_t & >(), std::forward< CompatibleType >(val))))
create a JSON value
Definition: json.hpp:1300
nlohmann::detail::parse_error
exception indicating a parse error
Definition: exceptions.hpp:118
nlohmann::basic_json::operator==
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5671
nlohmann::basic_json::operator>
friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:6008
nlohmann::detail::iter_impl
a template for a bidirectional iterator for the basic_json class This class implements a both iterato...
Definition: iter_impl.hpp:41
nlohmann::detail::internal_iterator::array_iterator
BasicJsonType::array_t::iterator array_iterator
iterator for JSON arrays
Definition: internal_iterator.hpp:20
nlohmann::detail::value_t::string
@ string
string value
nlohmann::basic_json::sax_parse
static bool sax_parse(detail::input_adapter &&i, SAX *sax, input_format_t format=input_format_t::json, const bool strict=true)
generate SAX events
Definition: json.hpp:6271
nlohmann::basic_json::is_string
constexpr bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2351
nlohmann::detail::error_handler_t
error_handler_t
how to treat decoding errors
Definition: serializer.hpp:35
nlohmann::basic_json::get
basic_json get() const
get special-case overload
Definition: json.hpp:2558
nlohmann::basic_json::is_discarded
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2378
nlohmann::basic_json::basic_json
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1806
nlohmann::basic_json::is_number_float
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2285
nlohmann::basic_json::operator<=
friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5962
nlohmann::basic_json::is_structured
constexpr bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:2126
nlohmann::basic_json::operator>
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5986
nlohmann::basic_json::crend
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4375
nlohmann::basic_json::operator>
friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
comparison: greater than
Definition: json.hpp:5997
nlohmann::basic_json::clear
void clear() noexcept
clears the contents
Definition: json.hpp:4792
nlohmann::basic_json::get_allocator
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:291
nlohmann::basic_json::operator>>
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:6401
nlohmann::basic_json::rbegin
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4280
nlohmann::basic_json::basic_json
basic_json(const BasicJsonType &val)
create a JSON value from an existing one
Definition: json.hpp:1337
nlohmann::basic_json::from_ubjson
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(A1 &&a1, A2 &&a2, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition: json.hpp:7187
nlohmann::detail::parser
syntax analysis
Definition: parser.hpp:34
nlohmann::basic_json::operator[]
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3217
nlohmann::basic_json::push_back
void push_back(initializer_list_t init)
add an object to an object
Definition: json.hpp:5005
nlohmann::basic_json::~basic_json
~basic_json() noexcept
destructor
Definition: json.hpp:1959
nlohmann::basic_json::emplace_back
reference emplace_back(Args &&... args)
add an object to an array
Definition: json.hpp:5053
nlohmann::basic_json::flatten
basic_json flatten() const
return flattened JSON value
Definition: json.hpp:7469
nlohmann::basic_json::end
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.hpp:4202
nlohmann::basic_json::operator+=
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4974
nlohmann::basic_json::number_unsigned_t
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:751
nlohmann::basic_json::parse
static basic_json parse(IteratorType first, IteratorType last, const parser_callback_t cb=nullptr, const bool allow_exceptions=true)
deserialize from an iterator range with contiguous storage
Definition: json.hpp:6334
nlohmann::detail::output_adapter_t
std::shared_ptr< output_adapter_protocol< CharType > > output_adapter_t
a type to simplify interfaces
Definition: output_adapters.hpp:27
nlohmann::detail::operator<
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: value_t.hpp:64
nlohmann::basic_json::operator==
friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5753
nlohmann::basic_json::is_number_unsigned
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2257
nlohmann::basic_json::back
reference back()
access the last element
Definition: json.hpp:3630
nlohmann::detail::input_format_t
input_format_t
the supported input formats
Definition: input_adapters.hpp:24
nlohmann::basic_json::at
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:2976
nlohmann::basic_json::is_object
constexpr bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2307
nlohmann::basic_json::basic_json
basic_json(const value_t v)
create an empty value with a given type
Definition: json.hpp:1209
nlohmann::basic_json::meta
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json meta()
returns version information on the library
Definition: json.hpp:323
nlohmann::json_pointer::pop_back
void pop_back()
remove last reference token
Definition: json_pointer.hpp:246
nlohmann::basic_json::to_cbor
static std::vector< uint8_t > to_cbor(const basic_json &j)
create a CBOR serialization of a given JSON value
Definition: json.hpp:6575
nlohmann::basic_json::unflatten
basic_json unflatten() const
unflatten a previously flattened JSON value
Definition: json.hpp:7506
nlohmann::basic_json::value
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:3482
nlohmann::basic_json::insert
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:5196
nlohmann::basic_json::erase
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:3924
nlohmann::basic_json::const_reverse_iterator
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
Definition: json.hpp:283
nlohmann::basic_json::string_t
StringType string_t
a type for a string
Definition: json.hpp:582
nlohmann::basic_json::contains
bool contains(const json_pointer &ptr) const
check the existence of an element in a JSON object given a JSON pointer
Definition: json.hpp:4092
nlohmann::basic_json::operator>=
friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:6043
nlohmann::basic_json::basic_json
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1617
nlohmann::basic_json::rend
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.hpp:4309
nlohmann::basic_json::get_ref
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:2871
nlohmann::basic_json::is_number
constexpr bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2200
nlohmann::basic_json::to_bson
static std::vector< 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:6845
nlohmann::basic_json::crbegin
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4346
nlohmann::detail::value_t::number_unsigned
@ number_unsigned
number value (unsigned integer)
nlohmann::basic_json::initializer_list_t
std::initializer_list< detail::json_ref< basic_json > > initializer_list_t
helper type for initializer lists of basic_json values
Definition: json.hpp:216
nlohmann::detail::binary_reader::sax_parse
bool sax_parse(const input_format_t format, json_sax_t *sax_, const bool strict=true)
Definition: binary_reader.hpp:70
nlohmann::detail::is_compatible_type
Definition: type_traits.hpp:359
nlohmann::detail::binary_reader
deserialization of CBOR, MessagePack, and UBJSON values
Definition: binary_reader.hpp:36
nlohmann::detail::value_t::array
@ array
array (ordered collection of values)
nlohmann::basic_json::at
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:3074
nlohmann::basic_json::push_back
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4863
nlohmann::basic_json::to_bson
static void to_bson(const basic_json &j, detail::output_adapter< uint8_t > o)
Serializes the given JSON object j to BSON and forwards the corresponding BSON-representation to the ...
Definition: json.hpp:6860
nlohmann::basic_json::size
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4652
nlohmann::basic_json::to_ubjson
static std::vector< 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:6768
libzip::source
std::function< struct zip_source *(struct zip *)> source
Source creation for adding files.
Definition: zip.hpp:122
nlohmann::basic_json::at
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:3125
nlohmann::detail::value_t::discarded
@ discarded
discarded by the the parser callback function
nlohmann::detail::parser::parse_event_t
parse_event_t
Definition: parser.hpp:44
nlohmann::detail::primitive_iterator_t
Definition: primitive_iterator.hpp:20
nlohmann::basic_json::from_cbor
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(A1 &&a1, A2 &&a2, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in CBOR format
Definition: json.hpp:6990
std::less<::nlohmann::detail::value_t >::operator()
bool operator()(nlohmann::detail::value_t lhs, nlohmann::detail::value_t rhs) const noexcept
compare two value_t enum values
Definition: json.hpp:8118
nlohmann::basic_json::get_ptr
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:2790
nlohmann::detail::value_t::boolean
@ boolean
boolean value
nlohmann::basic_json::emplace
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition: json.hpp:5106
nlohmann::basic_json::operator>=
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:6032
nlohmann::basic_json::get
constexpr auto get() const noexcept -> decltype(std::declval< const basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition: json.hpp:2837
nlohmann::basic_json::insert
iterator insert(const_iterator pos, initializer_list_t ilist)
inserts elements
Definition: json.hpp:5326
nlohmann::basic_json::from_bson
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(detail::input_adapter &&i, const bool strict=true, const bool allow_exceptions=true)
Create a JSON value from an input in BSON format.
Definition: json.hpp:7258
nlohmann::detail::serializer
Definition: serializer.hpp:43
nlohmann::basic_json::erase
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition: json.hpp:3802
nlohmann::basic_json::allocator_type
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:269
nlohmann::basic_json::operator<
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5829
nlohmann::detail::is_basic_json
Definition: type_traits.hpp:39
nlohmann::basic_json
a class to store JSON values
Definition: json.hpp:166
nlohmann::basic_json::operator==
friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
comparison: equal
Definition: json.hpp:5742
nlohmann::detail::parse_error::create
static parse_error create(int id_, const position_t &pos, const std::string &what_arg)
create a parse error exception
Definition: exceptions.hpp:129
nlohmann::basic_json::insert_iterator
iterator insert_iterator(const_iterator pos, Args &&... args)
Helper for insertion of an iterator.
Definition: json.hpp:5136
nlohmann::detail::input_adapter
Definition: input_adapters.hpp:335
nlohmann::basic_json::operator!=
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5776
nlohmann::basic_json::operator[]
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:3304
nlohmann::basic_json::swap
void swap(array_t &other)
exchanges the values
Definition: json.hpp:5543
nlohmann::basic_json::json_pointer
::nlohmann::json_pointer< basic_json > json_pointer
JSON Pointer, see nlohmann::json_pointer.
Definition: json.hpp:210
nlohmann::basic_json::parse_event_t
typename parser::parse_event_t parse_event_t
parser event types
Definition: json.hpp:1118
nlohmann::basic_json::front
const_reference front() const
access the first element
Definition: json.hpp:3594
nlohmann::basic_json::max_size
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4722
nlohmann::basic_json::operator[]
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3255
nlohmann::detail::parser::parse
void parse(const bool strict, BasicJsonType &result)
public parser interface
Definition: parser.hpp:82
nlohmann::basic_json::from_msgpack
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(detail::input_adapter &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition: json.hpp:7083
nlohmann::detail::internal_iterator
an iterator value
Definition: internal_iterator.hpp:16
nlohmann::basic_json::operator+=
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4924
nlohmann::basic_json::back
const_reference back() const
access the last element
Definition: json.hpp:3640
nlohmann::basic_json::at
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition: json.hpp:7399
nlohmann::basic_json::dump
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:2017
nlohmann::basic_json::value
ValueType value(const typename object_t::key_type &key, const ValueType &default_value) const
access specified object element with default value
Definition: json.hpp:3460
nlohmann::basic_json::push_back
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4950
nlohmann::basic_json::is_array
constexpr bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2329
nlohmann::basic_json::end
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4212
nlohmann::basic_json::from_bson
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(A1 &&a1, A2 &&a2, const bool strict=true, const bool allow_exceptions=true)
Create a JSON value from an input in BSON format.
Definition: json.hpp:7274
nlohmann::basic_json::operator<<
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:6099
nlohmann::basic_json::type_name
JSON_HEDLEY_RETURNS_NON_NULL const char * type_name() const noexcept
return the type as string
Definition: json.hpp:6444
nlohmann::basic_json::operator>>
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:6123
nlohmann::basic_json::get
auto get() noexcept -> decltype(std::declval< basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition: json.hpp:2825
nlohmann::basic_json::cbegin
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4171
nlohmann::basic_json::rbegin
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:4272
nlohmann::basic_json::const_pointer
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:274
nlohmann::basic_json::parse
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json parse(detail::input_adapter &&i, const parser_callback_t cb=nullptr, const bool allow_exceptions=true)
deserialize from a compatible input
Definition: json.hpp:6202
nlohmann::basic_json::pointer
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:272
nlohmann::basic_json::number_integer_t
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:680
nlohmann::json_sax
SAX interface.
Definition: json_sax.hpp:25
nlohmann::basic_json::operator>=
friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:6054
nlohmann::basic_json::from_cbor
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(detail::input_adapter &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in CBOR format
Definition: json.hpp:6974
nlohmann::detail::iteration_proxy
proxy class for the items() function
Definition: iteration_proxy.hpp:109
nlohmann::basic_json::diff
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:7863
nlohmann::basic_json::operator!=
friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
comparison: not equal
Definition: json.hpp:5787
nlohmann::basic_json::swap
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5609
nlohmann::basic_json::patch
basic_json patch(const basic_json &json_patch) const
applies a JSON patch
Definition: json.hpp:7567
nlohmann::basic_json::parser_callback_t
typename parser::parser_callback_t parser_callback_t
per-element parser callback type
Definition: json.hpp:1169
nlohmann::basic_json::type
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:2069
nlohmann::basic_json::operator+=
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4890
nlohmann::basic_json::operator<=
friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5951
nlohmann::basic_json::insert
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:5174
nlohmann::basic_json::iterator_wrapper
static iteration_proxy< iterator > iterator_wrapper(reference ref) noexcept
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4439
nlohmann::basic_json::items
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
Definition: json.hpp:4516
nlohmann::detail::binary_writer::write_bson
void write_bson(const BasicJsonType &j)
Definition: binary_writer.hpp:45
nlohmann::detail::output_adapter
Definition: output_adapters.hpp:103
nlohmann::basic_json::value
ValueType value(const json_pointer &ptr, const ValueType &default_value) const
access specified object element via JSON Pointer with default value
Definition: json.hpp:3532
nlohmann::basic_json::insert
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:5273
nlohmann::basic_json::basic_json
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition: json.hpp:1233
nlohmann::basic_json::get_ptr
auto get_ptr() noexcept -> decltype(std::declval< basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition: json.hpp:2777
nlohmann::basic_json::contains
bool contains(KeyT &&key) const
check the existence of an element in a JSON object
Definition: json.hpp:4061
nlohmann::basic_json::get_ref
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:2884
nlohmann::basic_json::operator<
friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5916
std::hash< nlohmann::json >::operator()
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
Definition: json.hpp:8100