Horizon
json.hpp
1 /*
2  __ _____ _____ _____
3  __| | __| | | | JSON for Modern C++
4 | | |__ | | | | | | version 3.1.0
5 |_____|_____|_____|_|___| https://github.com/nlohmann/json
6 
7 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8 Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
9 
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files (the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions:
16 
17 The above copyright notice and this permission notice shall be included in all
18 copies or substantial portions of the Software.
19 
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 SOFTWARE.
27 */
28 
29 #ifndef NLOHMANN_JSON_HPP
30 #define NLOHMANN_JSON_HPP
31 
32 #define NLOHMANN_JSON_VERSION_MAJOR 3
33 #define NLOHMANN_JSON_VERSION_MINOR 1
34 #define NLOHMANN_JSON_VERSION_PATCH 0
35 
36 #include <algorithm> // all_of, find, for_each
37 #include <cassert> // assert
38 #include <ciso646> // and, not, or
39 #include <cstddef> // nullptr_t, ptrdiff_t, size_t
40 #include <functional> // hash, less
41 #include <initializer_list> // initializer_list
42 #include <iosfwd> // istream, ostream
43 #include <iterator> // iterator_traits, random_access_iterator_tag
44 #include <numeric> // accumulate
45 #include <string> // string, stoi, to_string
46 #include <utility> // declval, forward, move, pair, swap
47 
48 #include <nlohmann/json_fwd.hpp>
49 #include <nlohmann/detail/macro_scope.hpp>
50 #include <nlohmann/detail/meta.hpp>
51 #include <nlohmann/detail/exceptions.hpp>
52 #include <nlohmann/detail/value_t.hpp>
53 #include <nlohmann/detail/conversions/from_json.hpp>
54 #include <nlohmann/detail/conversions/to_json.hpp>
55 #include <nlohmann/detail/input/input_adapters.hpp>
56 #include <nlohmann/detail/input/lexer.hpp>
57 #include <nlohmann/detail/input/parser.hpp>
58 #include <nlohmann/detail/iterators/primitive_iterator.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/output/output_adapters.hpp>
64 #include <nlohmann/detail/input/binary_reader.hpp>
65 #include <nlohmann/detail/output/binary_writer.hpp>
66 #include <nlohmann/detail/output/serializer.hpp>
67 #include <nlohmann/detail/json_ref.hpp>
68 #include <nlohmann/detail/json_pointer.hpp>
69 #include <nlohmann/adl_serializer.hpp>
70 
76 namespace nlohmann
77 {
78 
160 NLOHMANN_BASIC_JSON_TPL_DECLARATION
162 {
163  private:
164  template<detail::value_t> friend struct detail::external_constructor;
165  friend ::nlohmann::json_pointer<basic_json>;
166  friend ::nlohmann::detail::parser<basic_json>;
167  friend ::nlohmann::detail::serializer<basic_json>;
168  template<typename BasicJsonType>
169  friend class ::nlohmann::detail::iter_impl;
170  template<typename BasicJsonType, typename CharType>
171  friend class ::nlohmann::detail::binary_writer;
172  template<typename BasicJsonType>
173  friend class ::nlohmann::detail::binary_reader;
174 
176  using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
177 
178  // convenience aliases for types residing in namespace detail;
181 
183  template<typename BasicJsonType>
185  template<typename BasicJsonType>
187  template<typename Iterator>
190 
191  template<typename CharType>
192  using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
193 
196 
198 
199  public:
200  using value_t = detail::value_t;
203  template<typename T, typename SFINAE>
204  using json_serializer = JSONSerializer<T, SFINAE>;
206  using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
207 
209  // exceptions //
211 
215 
228 
230 
231 
233  // container types //
235 
240 
243 
247  using const_reference = const value_type&;
248 
250  using difference_type = std::ptrdiff_t;
252  using size_type = std::size_t;
253 
255  using allocator_type = AllocatorType<basic_json>;
256 
258  using pointer = typename std::allocator_traits<allocator_type>::pointer;
260  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
261 
270 
272 
273 
278  {
279  return allocator_type();
280  }
281 
308  static basic_json meta()
309  {
310  basic_json result;
311 
312  result["copyright"] = "(C) 2013-2017 Niels Lohmann";
313  result["name"] = "JSON for Modern C++";
314  result["url"] = "https://github.com/nlohmann/json";
315  result["version"]["string"] =
316  std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." +
317  std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." +
318  std::to_string(NLOHMANN_JSON_VERSION_PATCH);
319  result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
320  result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
321  result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
322 
323 #ifdef _WIN32
324  result["platform"] = "win32";
325 #elif defined __linux__
326  result["platform"] = "linux";
327 #elif defined __APPLE__
328  result["platform"] = "apple";
329 #elif defined __unix__
330  result["platform"] = "unix";
331 #else
332  result["platform"] = "unknown";
333 #endif
334 
335 #if defined(__ICC) || defined(__INTEL_COMPILER)
336  result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
337 #elif defined(__clang__)
338  result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
339 #elif defined(__GNUC__) || defined(__GNUG__)
340  result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
341 #elif defined(__HP_cc) || defined(__HP_aCC)
342  result["compiler"] = "hp"
343 #elif defined(__IBMCPP__)
344  result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
345 #elif defined(_MSC_VER)
346  result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
347 #elif defined(__PGI)
348  result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
349 #elif defined(__SUNPRO_CC)
350  result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
351 #else
352  result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
353 #endif
354 
355 #ifdef __cplusplus
356  result["compiler"]["c++"] = std::to_string(__cplusplus);
357 #else
358  result["compiler"]["c++"] = "unknown";
359 #endif
360  return result;
361  }
362 
363 
365  // JSON value data types //
367 
372 
373 #if defined(JSON_HAS_CPP_14)
374  // Use transparent comparator if possible, combined with perfect forwarding
375  // on find() and count() calls prevents unnecessary string construction.
376  using object_comparator_t = std::less<>;
377 #else
378  using object_comparator_t = std::less<StringType>;
379 #endif
380 
464  using object_t = ObjectType<StringType,
465  basic_json,
466  object_comparator_t,
467  AllocatorType<std::pair<const StringType,
469 
514  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
515 
567  using string_t = StringType;
568 
593  using boolean_t = BooleanType;
594 
665  using number_integer_t = NumberIntegerType;
666 
736  using number_unsigned_t = NumberUnsignedType;
737 
804  using number_float_t = NumberFloatType;
805 
807 
808  private:
809 
811  template<typename T, typename... Args>
812  static T* create(Args&& ... args)
813  {
814  AllocatorType<T> alloc;
815  using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
816 
817  auto deleter = [&](T * object)
818  {
819  AllocatorTraits::deallocate(alloc, object, 1);
820  };
821  std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
822  AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
823  assert(object != nullptr);
824  return object.release();
825  }
826 
828  // JSON value storage //
830 
855  union json_value
856  {
858  object_t* object;
860  array_t* array;
862  string_t* string;
864  boolean_t boolean;
866  number_integer_t number_integer;
868  number_unsigned_t number_unsigned;
870  number_float_t number_float;
871 
873  json_value() = default;
875  json_value(boolean_t v) noexcept : boolean(v) {}
877  json_value(number_integer_t v) noexcept : number_integer(v) {}
879  json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
881  json_value(number_float_t v) noexcept : number_float(v) {}
883  json_value(value_t t)
884  {
885  switch (t)
886  {
887  case value_t::object:
888  {
889  object = create<object_t>();
890  break;
891  }
892 
893  case value_t::array:
894  {
895  array = create<array_t>();
896  break;
897  }
898 
899  case value_t::string:
900  {
901  string = create<string_t>("");
902  break;
903  }
904 
905  case value_t::boolean:
906  {
907  boolean = boolean_t(false);
908  break;
909  }
910 
912  {
914  break;
915  }
916 
918  {
920  break;
921  }
922 
924  {
926  break;
927  }
928 
929  case value_t::null:
930  {
931  object = nullptr; // silence warning, see #821
932  break;
933  }
934 
935  default:
936  {
937  object = nullptr; // silence warning, see #821
938  if (JSON_UNLIKELY(t == value_t::null))
939  {
940  JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.1.0")); // LCOV_EXCL_LINE
941  }
942  break;
943  }
944  }
945  }
946 
948  json_value(const string_t& value)
949  {
950  string = create<string_t>(value);
951  }
952 
954  json_value(string_t&& value)
955  {
956  string = create<string_t>(std::move(value));
957  }
958 
960  json_value(const object_t& value)
961  {
962  object = create<object_t>(value);
963  }
964 
966  json_value(object_t&& value)
967  {
968  object = create<object_t>(std::move(value));
969  }
970 
972  json_value(const array_t& value)
973  {
974  array = create<array_t>(value);
975  }
976 
978  json_value(array_t&& value)
979  {
980  array = create<array_t>(std::move(value));
981  }
982 
983  void destroy(value_t t) noexcept
984  {
985  switch (t)
986  {
987  case value_t::object:
988  {
989  AllocatorType<object_t> alloc;
990  std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
991  std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
992  break;
993  }
994 
995  case value_t::array:
996  {
997  AllocatorType<array_t> alloc;
998  std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
999  std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
1000  break;
1001  }
1002 
1003  case value_t::string:
1004  {
1005  AllocatorType<string_t> alloc;
1006  std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
1007  std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
1008  break;
1009  }
1010 
1011  default:
1012  {
1013  break;
1014  }
1015  }
1016  }
1017  };
1018 
1028  void assert_invariant() const noexcept
1029  {
1030  assert(m_type != value_t::object or m_value.object != nullptr);
1031  assert(m_type != value_t::array or m_value.array != nullptr);
1032  assert(m_type != value_t::string or m_value.string != nullptr);
1033  }
1034 
1035  public:
1037  // JSON parser callback //
1039 
1056 
1106  using parser_callback_t = typename parser::parser_callback_t;
1107 
1108 
1110  // constructors //
1112 
1117 
1148  : m_type(v), m_value(v)
1149  {
1150  assert_invariant();
1151  }
1152 
1171  basic_json(std::nullptr_t = nullptr) noexcept
1172  : basic_json(value_t::null)
1173  {
1174  assert_invariant();
1175  }
1176 
1233  template <typename CompatibleType,
1234  typename U = detail::uncvref_t<CompatibleType>,
1235  detail::enable_if_t<
1237  basic_json(CompatibleType && val) noexcept(noexcept(
1238  JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
1239  std::forward<CompatibleType>(val))))
1240  {
1241  JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
1242  assert_invariant();
1243  }
1244 
1320  bool type_deduction = true,
1321  value_t manual_type = value_t::array)
1322  {
1323  // check if each element is an array with two elements whose first
1324  // element is a string
1325  bool is_an_object = std::all_of(init.begin(), init.end(),
1326  [](const detail::json_ref<basic_json>& element_ref)
1327  {
1328  return (element_ref->is_array() and element_ref->size() == 2 and (*element_ref)[0].is_string());
1329  });
1330 
1331  // adjust type if type deduction is not wanted
1332  if (not type_deduction)
1333  {
1334  // if array is wanted, do not create an object though possible
1335  if (manual_type == value_t::array)
1336  {
1337  is_an_object = false;
1338  }
1339 
1340  // if object is wanted but impossible, throw an exception
1341  if (JSON_UNLIKELY(manual_type == value_t::object and not is_an_object))
1342  {
1343  JSON_THROW(type_error::create(301, "cannot create object from initializer list"));
1344  }
1345  }
1346 
1347  if (is_an_object)
1348  {
1349  // the initializer list is a list of pairs -> create object
1350  m_type = value_t::object;
1351  m_value = value_t::object;
1352 
1353  std::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref)
1354  {
1355  auto element = element_ref.moved_or_copied();
1356  m_value.object->emplace(
1357  std::move(*((*element.m_value.array)[0].m_value.string)),
1358  std::move((*element.m_value.array)[1]));
1359  });
1360  }
1361  else
1362  {
1363  // the initializer list describes an array -> create array
1364  m_type = value_t::array;
1365  m_value.array = create<array_t>(init.begin(), init.end());
1366  }
1367 
1368  assert_invariant();
1369  }
1370 
1409  {
1410  return basic_json(init, false, value_t::array);
1411  }
1412 
1452  {
1453  return basic_json(init, false, value_t::object);
1454  }
1455 
1479  : m_type(value_t::array)
1480  {
1481  m_value.array = create<array_t>(cnt, val);
1482  assert_invariant();
1483  }
1484 
1540  template<class InputIT, typename std::enable_if<
1541  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1542  std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>
1543  basic_json(InputIT first, InputIT last)
1544  {
1545  assert(first.m_object != nullptr);
1546  assert(last.m_object != nullptr);
1547 
1548  // make sure iterator fits the current value
1549  if (JSON_UNLIKELY(first.m_object != last.m_object))
1550  {
1551  JSON_THROW(invalid_iterator::create(201, "iterators are not compatible"));
1552  }
1553 
1554  // copy type from first iterator
1555  m_type = first.m_object->m_type;
1556 
1557  // check if iterator range is complete for primitive values
1558  switch (m_type)
1559  {
1560  case value_t::boolean:
1561  case value_t::number_float:
1564  case value_t::string:
1565  {
1566  if (JSON_UNLIKELY(not first.m_it.primitive_iterator.is_begin()
1567  or not last.m_it.primitive_iterator.is_end()))
1568  {
1569  JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
1570  }
1571  break;
1572  }
1573 
1574  default:
1575  break;
1576  }
1577 
1578  switch (m_type)
1579  {
1581  {
1582  m_value.number_integer = first.m_object->m_value.number_integer;
1583  break;
1584  }
1585 
1587  {
1588  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1589  break;
1590  }
1591 
1592  case value_t::number_float:
1593  {
1594  m_value.number_float = first.m_object->m_value.number_float;
1595  break;
1596  }
1597 
1598  case value_t::boolean:
1599  {
1600  m_value.boolean = first.m_object->m_value.boolean;
1601  break;
1602  }
1603 
1604  case value_t::string:
1605  {
1606  m_value = *first.m_object->m_value.string;
1607  break;
1608  }
1609 
1610  case value_t::object:
1611  {
1612  m_value.object = create<object_t>(first.m_it.object_iterator,
1613  last.m_it.object_iterator);
1614  break;
1615  }
1616 
1617  case value_t::array:
1618  {
1619  m_value.array = create<array_t>(first.m_it.array_iterator,
1620  last.m_it.array_iterator);
1621  break;
1622  }
1623 
1624  default:
1625  JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " +
1626  std::string(first.m_object->type_name())));
1627  }
1628 
1629  assert_invariant();
1630  }
1631 
1632 
1634  // other constructors and destructor //
1636 
1639  : basic_json(ref.moved_or_copied())
1640  {}
1641 
1667  basic_json(const basic_json& other)
1668  : m_type(other.m_type)
1669  {
1670  // check of passed value is valid
1671  other.assert_invariant();
1672 
1673  switch (m_type)
1674  {
1675  case value_t::object:
1676  {
1677  m_value = *other.m_value.object;
1678  break;
1679  }
1680 
1681  case value_t::array:
1682  {
1683  m_value = *other.m_value.array;
1684  break;
1685  }
1686 
1687  case value_t::string:
1688  {
1689  m_value = *other.m_value.string;
1690  break;
1691  }
1692 
1693  case value_t::boolean:
1694  {
1695  m_value = other.m_value.boolean;
1696  break;
1697  }
1698 
1700  {
1701  m_value = other.m_value.number_integer;
1702  break;
1703  }
1704 
1706  {
1707  m_value = other.m_value.number_unsigned;
1708  break;
1709  }
1710 
1711  case value_t::number_float:
1712  {
1713  m_value = other.m_value.number_float;
1714  break;
1715  }
1716 
1717  default:
1718  break;
1719  }
1720 
1721  assert_invariant();
1722  }
1723 
1750  basic_json(basic_json&& other) noexcept
1751  : m_type(std::move(other.m_type)),
1752  m_value(std::move(other.m_value))
1753  {
1754  // check that passed value is valid
1755  other.assert_invariant();
1756 
1757  // invalidate payload
1758  other.m_type = value_t::null;
1759  other.m_value = {};
1760 
1761  assert_invariant();
1762  }
1763 
1787  reference& operator=(basic_json other) noexcept (
1788  std::is_nothrow_move_constructible<value_t>::value and
1789  std::is_nothrow_move_assignable<value_t>::value and
1790  std::is_nothrow_move_constructible<json_value>::value and
1791  std::is_nothrow_move_assignable<json_value>::value
1792  )
1793  {
1794  // check that passed value is valid
1795  other.assert_invariant();
1796 
1797  using std::swap;
1798  swap(m_type, other.m_type);
1799  swap(m_value, other.m_value);
1800 
1801  assert_invariant();
1802  return *this;
1803  }
1804 
1820  ~basic_json() noexcept
1821  {
1822  assert_invariant();
1823  m_value.destroy(m_type);
1824  }
1825 
1827 
1828  public:
1830  // object inspection //
1832 
1836 
1873  string_t dump(const int indent = -1, const char indent_char = ' ',
1874  const bool ensure_ascii = false) const
1875  {
1876  string_t result;
1877  serializer s(detail::output_adapter<char>(result), indent_char);
1878 
1879  if (indent >= 0)
1880  {
1881  s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
1882  }
1883  else
1884  {
1885  s.dump(*this, false, ensure_ascii, 0);
1886  }
1887 
1888  return result;
1889  }
1890 
1923  constexpr value_t type() const noexcept
1924  {
1925  return m_type;
1926  }
1927 
1953  constexpr bool is_primitive() const noexcept
1954  {
1955  return is_null() or is_string() or is_boolean() or is_number();
1956  }
1957 
1980  constexpr bool is_structured() const noexcept
1981  {
1982  return is_array() or is_object();
1983  }
1984 
2002  constexpr bool is_null() const noexcept
2003  {
2004  return (m_type == value_t::null);
2005  }
2006 
2024  constexpr bool is_boolean() const noexcept
2025  {
2026  return (m_type == value_t::boolean);
2027  }
2028 
2054  constexpr bool is_number() const noexcept
2055  {
2056  return is_number_integer() or is_number_float();
2057  }
2058 
2083  constexpr bool is_number_integer() const noexcept
2084  {
2085  return (m_type == value_t::number_integer or m_type == value_t::number_unsigned);
2086  }
2087 
2111  constexpr bool is_number_unsigned() const noexcept
2112  {
2113  return (m_type == value_t::number_unsigned);
2114  }
2115 
2139  constexpr bool is_number_float() const noexcept
2140  {
2141  return (m_type == value_t::number_float);
2142  }
2143 
2161  constexpr bool is_object() const noexcept
2162  {
2163  return (m_type == value_t::object);
2164  }
2165 
2183  constexpr bool is_array() const noexcept
2184  {
2185  return (m_type == value_t::array);
2186  }
2187 
2205  constexpr bool is_string() const noexcept
2206  {
2207  return (m_type == value_t::string);
2208  }
2209 
2232  constexpr bool is_discarded() const noexcept
2233  {
2234  return (m_type == value_t::discarded);
2235  }
2236 
2258  constexpr operator value_t() const noexcept
2259  {
2260  return m_type;
2261  }
2262 
2264 
2265  private:
2267  // value access //
2269 
2271  boolean_t get_impl(boolean_t* /*unused*/) const
2272  {
2273  if (JSON_LIKELY(is_boolean()))
2274  {
2275  return m_value.boolean;
2276  }
2277 
2278  JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name())));
2279  }
2280 
2282  object_t* get_impl_ptr(object_t* /*unused*/) noexcept
2283  {
2284  return is_object() ? m_value.object : nullptr;
2285  }
2286 
2288  constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
2289  {
2290  return is_object() ? m_value.object : nullptr;
2291  }
2292 
2294  array_t* get_impl_ptr(array_t* /*unused*/) noexcept
2295  {
2296  return is_array() ? m_value.array : nullptr;
2297  }
2298 
2300  constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
2301  {
2302  return is_array() ? m_value.array : nullptr;
2303  }
2304 
2306  string_t* get_impl_ptr(string_t* /*unused*/) noexcept
2307  {
2308  return is_string() ? m_value.string : nullptr;
2309  }
2310 
2312  constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
2313  {
2314  return is_string() ? m_value.string : nullptr;
2315  }
2316 
2318  boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
2319  {
2320  return is_boolean() ? &m_value.boolean : nullptr;
2321  }
2322 
2324  constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
2325  {
2326  return is_boolean() ? &m_value.boolean : nullptr;
2327  }
2328 
2330  number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
2331  {
2332  return is_number_integer() ? &m_value.number_integer : nullptr;
2333  }
2334 
2336  constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
2337  {
2338  return is_number_integer() ? &m_value.number_integer : nullptr;
2339  }
2340 
2342  number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
2343  {
2344  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2345  }
2346 
2348  constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
2349  {
2350  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2351  }
2352 
2354  number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
2355  {
2356  return is_number_float() ? &m_value.number_float : nullptr;
2357  }
2358 
2360  constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
2361  {
2362  return is_number_float() ? &m_value.number_float : nullptr;
2363  }
2364 
2376  template<typename ReferenceType, typename ThisType>
2377  static ReferenceType get_ref_impl(ThisType& obj)
2378  {
2379  // delegate the call to get_ptr<>()
2380  auto ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
2381 
2382  if (JSON_LIKELY(ptr != nullptr))
2383  {
2384  return *ptr;
2385  }
2386 
2387  JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name())));
2388  }
2389 
2390  public:
2394 
2409  template<typename BasicJsonType, detail::enable_if_t<
2410  std::is_same<typename std::remove_const<BasicJsonType>::type, basic_json_t>::value,
2411  int> = 0>
2412  basic_json get() const
2413  {
2414  return *this;
2415  }
2416 
2456  template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
2457  detail::enable_if_t <
2458  not std::is_same<basic_json_t, ValueType>::value and
2459  detail::has_from_json<basic_json_t, ValueType>::value and
2460  not detail::has_non_default_from_json<basic_json_t, ValueType>::value,
2461  int> = 0>
2462  ValueType get() const noexcept(noexcept(
2463  JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
2464  {
2465  // we cannot static_assert on ValueTypeCV being non-const, because
2466  // there is support for get<const basic_json_t>(), which is why we
2467  // still need the uncvref
2468  static_assert(not std::is_reference<ValueTypeCV>::value,
2469  "get() cannot be used with reference types, you might want to use get_ref()");
2470  static_assert(std::is_default_constructible<ValueType>::value,
2471  "types must be DefaultConstructible when used with get()");
2472 
2473  ValueType ret;
2474  JSONSerializer<ValueType>::from_json(*this, ret);
2475  return ret;
2476  }
2477 
2509  template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
2510  detail::enable_if_t<not std::is_same<basic_json_t, ValueType>::value and
2511  detail::has_non_default_from_json<basic_json_t, ValueType>::value,
2512  int> = 0>
2513  ValueType get() const noexcept(noexcept(
2514  JSONSerializer<ValueTypeCV>::from_json(std::declval<const basic_json_t&>())))
2515  {
2516  static_assert(not std::is_reference<ValueTypeCV>::value,
2517  "get() cannot be used with reference types, you might want to use get_ref()");
2518  return JSONSerializer<ValueTypeCV>::from_json(*this);
2519  }
2520 
2548  template<typename PointerType, typename std::enable_if<
2549  std::is_pointer<PointerType>::value, int>::type = 0>
2550  PointerType get() noexcept
2551  {
2552  // delegate the call to get_ptr
2553  return get_ptr<PointerType>();
2554  }
2555 
2560  template<typename PointerType, typename std::enable_if<
2561  std::is_pointer<PointerType>::value, int>::type = 0>
2562  constexpr const PointerType get() const noexcept
2563  {
2564  // delegate the call to get_ptr
2565  return get_ptr<PointerType>();
2566  }
2567 
2594  template<typename PointerType, typename std::enable_if<
2595  std::is_pointer<PointerType>::value, int>::type = 0>
2596  PointerType get_ptr() noexcept
2597  {
2598  // get the type of the PointerType (remove pointer and const)
2599  using pointee_t = typename std::remove_const<typename
2600  std::remove_pointer<typename
2601  std::remove_const<PointerType>::type>::type>::type;
2602  // make sure the type matches the allowed types
2603  static_assert(
2604  std::is_same<object_t, pointee_t>::value
2605  or std::is_same<array_t, pointee_t>::value
2606  or std::is_same<string_t, pointee_t>::value
2607  or std::is_same<boolean_t, pointee_t>::value
2608  or std::is_same<number_integer_t, pointee_t>::value
2609  or std::is_same<number_unsigned_t, pointee_t>::value
2610  or std::is_same<number_float_t, pointee_t>::value
2611  , "incompatible pointer type");
2612 
2613  // delegate the call to get_impl_ptr<>()
2614  return get_impl_ptr(static_cast<PointerType>(nullptr));
2615  }
2616 
2621  template<typename PointerType, typename std::enable_if<
2622  std::is_pointer<PointerType>::value and
2623  std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
2624  constexpr const PointerType get_ptr() const noexcept
2625  {
2626  // get the type of the PointerType (remove pointer and const)
2627  using pointee_t = typename std::remove_const<typename
2628  std::remove_pointer<typename
2629  std::remove_const<PointerType>::type>::type>::type;
2630  // make sure the type matches the allowed types
2631  static_assert(
2632  std::is_same<object_t, pointee_t>::value
2633  or std::is_same<array_t, pointee_t>::value
2634  or std::is_same<string_t, pointee_t>::value
2635  or std::is_same<boolean_t, pointee_t>::value
2636  or std::is_same<number_integer_t, pointee_t>::value
2637  or std::is_same<number_unsigned_t, pointee_t>::value
2638  or std::is_same<number_float_t, pointee_t>::value
2639  , "incompatible pointer type");
2640 
2641  // delegate the call to get_impl_ptr<>() const
2642  return get_impl_ptr(static_cast<PointerType>(nullptr));
2643  }
2644 
2671  template<typename ReferenceType, typename std::enable_if<
2672  std::is_reference<ReferenceType>::value, int>::type = 0>
2673  ReferenceType get_ref()
2674  {
2675  // delegate call to get_ref_impl
2676  return get_ref_impl<ReferenceType>(*this);
2677  }
2678 
2683  template<typename ReferenceType, typename std::enable_if<
2684  std::is_reference<ReferenceType>::value and
2685  std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
2686  ReferenceType get_ref() const
2687  {
2688  // delegate call to get_ref_impl
2689  return get_ref_impl<ReferenceType>(*this);
2690  }
2691 
2721  template < typename ValueType, typename std::enable_if <
2722  not std::is_pointer<ValueType>::value and
2723  not std::is_same<ValueType, detail::json_ref<basic_json>>::value and
2724  not std::is_same<ValueType, typename string_t::value_type>::value
2725 #ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015
2726  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
2727 #endif
2728 #if defined(JSON_HAS_CPP_17)
2729  and not std::is_same<ValueType, typename std::string_view>::value
2730 #endif
2731  , int >::type = 0 >
2732  operator ValueType() const
2733  {
2734  // delegate the call to get<>() const
2735  return get<ValueType>();
2736  }
2737 
2739 
2740 
2742  // element access //
2744 
2748 
2776  {
2777  // at only works for arrays
2778  if (JSON_LIKELY(is_array()))
2779  {
2780  JSON_TRY
2781  {
2782  return m_value.array->at(idx);
2783  }
2784  JSON_CATCH (std::out_of_range&)
2785  {
2786  // create better exception explanation
2787  JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
2788  }
2789  }
2790  else
2791  {
2792  JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
2793  }
2794  }
2795 
2823  {
2824  // at only works for arrays
2825  if (JSON_LIKELY(is_array()))
2826  {
2827  JSON_TRY
2828  {
2829  return m_value.array->at(idx);
2830  }
2831  JSON_CATCH (std::out_of_range&)
2832  {
2833  // create better exception explanation
2834  JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
2835  }
2836  }
2837  else
2838  {
2839  JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
2840  }
2841  }
2842 
2873  reference at(const typename object_t::key_type& key)
2874  {
2875  // at only works for objects
2876  if (JSON_LIKELY(is_object()))
2877  {
2878  JSON_TRY
2879  {
2880  return m_value.object->at(key);
2881  }
2882  JSON_CATCH (std::out_of_range&)
2883  {
2884  // create better exception explanation
2885  JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
2886  }
2887  }
2888  else
2889  {
2890  JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
2891  }
2892  }
2893 
2924  const_reference at(const typename object_t::key_type& key) const
2925  {
2926  // at only works for objects
2927  if (JSON_LIKELY(is_object()))
2928  {
2929  JSON_TRY
2930  {
2931  return m_value.object->at(key);
2932  }
2933  JSON_CATCH (std::out_of_range&)
2934  {
2935  // create better exception explanation
2936  JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
2937  }
2938  }
2939  else
2940  {
2941  JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
2942  }
2943  }
2944 
2971  {
2972  // implicitly convert null value to an empty array
2973  if (is_null())
2974  {
2975  m_type = value_t::array;
2976  m_value.array = create<array_t>();
2977  assert_invariant();
2978  }
2979 
2980  // operator[] only works for arrays
2981  if (JSON_LIKELY(is_array()))
2982  {
2983  // fill up array with null values if given idx is outside range
2984  if (idx >= m_value.array->size())
2985  {
2986  m_value.array->insert(m_value.array->end(),
2987  idx - m_value.array->size() + 1,
2988  basic_json());
2989  }
2990 
2991  return m_value.array->operator[](idx);
2992  }
2993 
2994  JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
2995  }
2996 
3017  {
3018  // const operator[] only works for arrays
3019  if (JSON_LIKELY(is_array()))
3020  {
3021  return m_value.array->operator[](idx);
3022  }
3023 
3024  JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
3025  }
3026 
3054  reference operator[](const typename object_t::key_type& key)
3055  {
3056  // implicitly convert null value to an empty object
3057  if (is_null())
3058  {
3059  m_type = value_t::object;
3060  m_value.object = create<object_t>();
3061  assert_invariant();
3062  }
3063 
3064  // operator[] only works for objects
3065  if (JSON_LIKELY(is_object()))
3066  {
3067  return m_value.object->operator[](key);
3068  }
3069 
3070  JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
3071  }
3072 
3103  const_reference operator[](const typename object_t::key_type& key) const
3104  {
3105  // const operator[] only works for objects
3106  if (JSON_LIKELY(is_object()))
3107  {
3108  assert(m_value.object->find(key) != m_value.object->end());
3109  return m_value.object->find(key)->second;
3110  }
3111 
3112  JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
3113  }
3114 
3142  template<typename T>
3144  {
3145  // implicitly convert null to object
3146  if (is_null())
3147  {
3148  m_type = value_t::object;
3149  m_value = value_t::object;
3150  assert_invariant();
3151  }
3152 
3153  // at only works for objects
3154  if (JSON_LIKELY(is_object()))
3155  {
3156  return m_value.object->operator[](key);
3157  }
3158 
3159  JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
3160  }
3161 
3192  template<typename T>
3194  {
3195  // at only works for objects
3196  if (JSON_LIKELY(is_object()))
3197  {
3198  assert(m_value.object->find(key) != m_value.object->end());
3199  return m_value.object->find(key)->second;
3200  }
3201 
3202  JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
3203  }
3204 
3253  template<class ValueType, typename std::enable_if<
3254  std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
3255  ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
3256  {
3257  // at only works for objects
3258  if (JSON_LIKELY(is_object()))
3259  {
3260  // if key is found, return value and given default value otherwise
3261  const auto it = find(key);
3262  if (it != end())
3263  {
3264  return *it;
3265  }
3266 
3267  return default_value;
3268  }
3269 
3270  JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
3271  }
3272 
3277  string_t value(const typename object_t::key_type& key, const char* default_value) const
3278  {
3279  return value(key, string_t(default_value));
3280  }
3281 
3323  template<class ValueType, typename std::enable_if<
3324  std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
3325  ValueType value(const json_pointer& ptr, const ValueType& default_value) const
3326  {
3327  // at only works for objects
3328  if (JSON_LIKELY(is_object()))
3329  {
3330  // if pointer resolves a value, return it or use default value
3331  JSON_TRY
3332  {
3333  return ptr.get_checked(this);
3334  }
3335  JSON_CATCH (out_of_range&)
3336  {
3337  return default_value;
3338  }
3339  }
3340 
3341  JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
3342  }
3343 
3348  string_t value(const json_pointer& ptr, const char* default_value) const
3349  {
3350  return value(ptr, string_t(default_value));
3351  }
3352 
3379  {
3380  return *begin();
3381  }
3382 
3387  {
3388  return *cbegin();
3389  }
3390 
3423  {
3424  auto tmp = end();
3425  --tmp;
3426  return *tmp;
3427  }
3428 
3433  {
3434  auto tmp = cend();
3435  --tmp;
3436  return *tmp;
3437  }
3438 
3485  template<class IteratorType, typename std::enable_if<
3486  std::is_same<IteratorType, typename basic_json_t::iterator>::value or
3487  std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
3488  = 0>
3489  IteratorType erase(IteratorType pos)
3490  {
3491  // make sure iterator fits the current value
3492  if (JSON_UNLIKELY(this != pos.m_object))
3493  {
3494  JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
3495  }
3496 
3497  IteratorType result = end();
3498 
3499  switch (m_type)
3500  {
3501  case value_t::boolean:
3502  case value_t::number_float:
3505  case value_t::string:
3506  {
3507  if (JSON_UNLIKELY(not pos.m_it.primitive_iterator.is_begin()))
3508  {
3509  JSON_THROW(invalid_iterator::create(205, "iterator out of range"));
3510  }
3511 
3512  if (is_string())
3513  {
3514  AllocatorType<string_t> alloc;
3515  std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
3516  std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
3517  m_value.string = nullptr;
3518  }
3519 
3520  m_type = value_t::null;
3521  assert_invariant();
3522  break;
3523  }
3524 
3525  case value_t::object:
3526  {
3527  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3528  break;
3529  }
3530 
3531  case value_t::array:
3532  {
3533  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3534  break;
3535  }
3536 
3537  default:
3538  JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
3539  }
3540 
3541  return result;
3542  }
3543 
3590  template<class IteratorType, typename std::enable_if<
3591  std::is_same<IteratorType, typename basic_json_t::iterator>::value or
3592  std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
3593  = 0>
3594  IteratorType erase(IteratorType first, IteratorType last)
3595  {
3596  // make sure iterator fits the current value
3597  if (JSON_UNLIKELY(this != first.m_object or this != last.m_object))
3598  {
3599  JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value"));
3600  }
3601 
3602  IteratorType result = end();
3603 
3604  switch (m_type)
3605  {
3606  case value_t::boolean:
3607  case value_t::number_float:
3610  case value_t::string:
3611  {
3612  if (JSON_LIKELY(not first.m_it.primitive_iterator.is_begin()
3613  or not last.m_it.primitive_iterator.is_end()))
3614  {
3615  JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
3616  }
3617 
3618  if (is_string())
3619  {
3620  AllocatorType<string_t> alloc;
3621  std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
3622  std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
3623  m_value.string = nullptr;
3624  }
3625 
3626  m_type = value_t::null;
3627  assert_invariant();
3628  break;
3629  }
3630 
3631  case value_t::object:
3632  {
3633  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3634  last.m_it.object_iterator);
3635  break;
3636  }
3637 
3638  case value_t::array:
3639  {
3640  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3641  last.m_it.array_iterator);
3642  break;
3643  }
3644 
3645  default:
3646  JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
3647  }
3648 
3649  return result;
3650  }
3651 
3681  size_type erase(const typename object_t::key_type& key)
3682  {
3683  // this erase only works for objects
3684  if (JSON_LIKELY(is_object()))
3685  {
3686  return m_value.object->erase(key);
3687  }
3688 
3689  JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
3690  }
3691 
3716  void erase(const size_type idx)
3717  {
3718  // this erase only works for arrays
3719  if (JSON_LIKELY(is_array()))
3720  {
3721  if (JSON_UNLIKELY(idx >= size()))
3722  {
3723  JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
3724  }
3725 
3726  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
3727  }
3728  else
3729  {
3730  JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
3731  }
3732  }
3733 
3735 
3736 
3738  // lookup //
3740 
3743 
3766  template<typename KeyT>
3767  iterator find(KeyT&& key)
3768  {
3769  auto result = end();
3770 
3771  if (is_object())
3772  {
3773  result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
3774  }
3775 
3776  return result;
3777  }
3778 
3783  template<typename KeyT>
3784  const_iterator find(KeyT&& key) const
3785  {
3786  auto result = cend();
3787 
3788  if (is_object())
3789  {
3790  result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
3791  }
3792 
3793  return result;
3794  }
3795 
3817  template<typename KeyT>
3818  size_type count(KeyT&& key) const
3819  {
3820  // return 0 for all nonobject types
3821  return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
3822  }
3823 
3825 
3826 
3828  // iterators //
3830 
3833 
3858  iterator begin() noexcept
3859  {
3860  iterator result(this);
3861  result.set_begin();
3862  return result;
3863  }
3864 
3868  const_iterator begin() const noexcept
3869  {
3870  return cbegin();
3871  }
3872 
3898  const_iterator cbegin() const noexcept
3899  {
3900  const_iterator result(this);
3901  result.set_begin();
3902  return result;
3903  }
3904 
3929  iterator end() noexcept
3930  {
3931  iterator result(this);
3932  result.set_end();
3933  return result;
3934  }
3935 
3939  const_iterator end() const noexcept
3940  {
3941  return cend();
3942  }
3943 
3969  const_iterator cend() const noexcept
3970  {
3971  const_iterator result(this);
3972  result.set_end();
3973  return result;
3974  }
3975 
4000  {
4001  return reverse_iterator(end());
4002  }
4003 
4008  {
4009  return crbegin();
4010  }
4011 
4037  {
4038  return reverse_iterator(begin());
4039  }
4040 
4044  const_reverse_iterator rend() const noexcept
4045  {
4046  return crend();
4047  }
4048 
4074  {
4075  return const_reverse_iterator(cend());
4076  }
4077 
4103  {
4104  return const_reverse_iterator(cbegin());
4105  }
4106 
4107  public:
4165  JSON_DEPRECATED
4167  {
4168  return ref.items();
4169  }
4170 
4174  JSON_DEPRECATED
4176  {
4177  return ref.items();
4178  }
4179 
4233  {
4234  return iteration_proxy<iterator>(*this);
4235  }
4236 
4241  {
4242  return iteration_proxy<const_iterator>(*this);
4243  }
4244 
4246 
4247 
4249  // capacity //
4251 
4254 
4296  bool empty() const noexcept
4297  {
4298  switch (m_type)
4299  {
4300  case value_t::null:
4301  {
4302  // null values are empty
4303  return true;
4304  }
4305 
4306  case value_t::array:
4307  {
4308  // delegate call to array_t::empty()
4309  return m_value.array->empty();
4310  }
4311 
4312  case value_t::object:
4313  {
4314  // delegate call to object_t::empty()
4315  return m_value.object->empty();
4316  }
4317 
4318  default:
4319  {
4320  // all other types are nonempty
4321  return false;
4322  }
4323  }
4324  }
4325 
4368  size_type size() const noexcept
4369  {
4370  switch (m_type)
4371  {
4372  case value_t::null:
4373  {
4374  // null values are empty
4375  return 0;
4376  }
4377 
4378  case value_t::array:
4379  {
4380  // delegate call to array_t::size()
4381  return m_value.array->size();
4382  }
4383 
4384  case value_t::object:
4385  {
4386  // delegate call to object_t::size()
4387  return m_value.object->size();
4388  }
4389 
4390  default:
4391  {
4392  // all other types have size 1
4393  return 1;
4394  }
4395  }
4396  }
4397 
4438  size_type max_size() const noexcept
4439  {
4440  switch (m_type)
4441  {
4442  case value_t::array:
4443  {
4444  // delegate call to array_t::max_size()
4445  return m_value.array->max_size();
4446  }
4447 
4448  case value_t::object:
4449  {
4450  // delegate call to object_t::max_size()
4451  return m_value.object->max_size();
4452  }
4453 
4454  default:
4455  {
4456  // all other types have max_size() == size()
4457  return size();
4458  }
4459  }
4460  }
4461 
4463 
4464 
4466  // modifiers //
4468 
4471 
4508  void clear() noexcept
4509  {
4510  switch (m_type)
4511  {
4513  {
4514  m_value.number_integer = 0;
4515  break;
4516  }
4517 
4519  {
4520  m_value.number_unsigned = 0;
4521  break;
4522  }
4523 
4524  case value_t::number_float:
4525  {
4526  m_value.number_float = 0.0;
4527  break;
4528  }
4529 
4530  case value_t::boolean:
4531  {
4532  m_value.boolean = false;
4533  break;
4534  }
4535 
4536  case value_t::string:
4537  {
4538  m_value.string->clear();
4539  break;
4540  }
4541 
4542  case value_t::array:
4543  {
4544  m_value.array->clear();
4545  break;
4546  }
4547 
4548  case value_t::object:
4549  {
4550  m_value.object->clear();
4551  break;
4552  }
4553 
4554  default:
4555  break;
4556  }
4557  }
4558 
4579  void push_back(basic_json&& val)
4580  {
4581  // push_back only works for null objects or arrays
4582  if (JSON_UNLIKELY(not(is_null() or is_array())))
4583  {
4584  JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
4585  }
4586 
4587  // transform null object into an array
4588  if (is_null())
4589  {
4590  m_type = value_t::array;
4591  m_value = value_t::array;
4592  assert_invariant();
4593  }
4594 
4595  // add element to array (move semantics)
4596  m_value.array->push_back(std::move(val));
4597  // invalidate object
4598  val.m_type = value_t::null;
4599  }
4600 
4606  {
4607  push_back(std::move(val));
4608  return *this;
4609  }
4610 
4615  void push_back(const basic_json& val)
4616  {
4617  // push_back only works for null objects or arrays
4618  if (JSON_UNLIKELY(not(is_null() or is_array())))
4619  {
4620  JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
4621  }
4622 
4623  // transform null object into an array
4624  if (is_null())
4625  {
4626  m_type = value_t::array;
4627  m_value = value_t::array;
4628  assert_invariant();
4629  }
4630 
4631  // add element to array
4632  m_value.array->push_back(val);
4633  }
4634 
4640  {
4641  push_back(val);
4642  return *this;
4643  }
4644 
4665  void push_back(const typename object_t::value_type& val)
4666  {
4667  // push_back only works for null objects or objects
4668  if (JSON_UNLIKELY(not(is_null() or is_object())))
4669  {
4670  JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
4671  }
4672 
4673  // transform null object into an object
4674  if (is_null())
4675  {
4676  m_type = value_t::object;
4677  m_value = value_t::object;
4678  assert_invariant();
4679  }
4680 
4681  // add element to array
4682  m_value.object->insert(val);
4683  }
4684 
4689  reference operator+=(const typename object_t::value_type& val)
4690  {
4691  push_back(val);
4692  return *this;
4693  }
4694 
4721  {
4722  if (is_object() and init.size() == 2 and (*init.begin())->is_string())
4723  {
4724  basic_json&& key = init.begin()->moved_or_copied();
4725  push_back(typename object_t::value_type(
4726  std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
4727  }
4728  else
4729  {
4730  push_back(basic_json(init));
4731  }
4732  }
4733 
4739  {
4740  push_back(init);
4741  return *this;
4742  }
4743 
4765  template<class... Args>
4766  void emplace_back(Args&& ... args)
4767  {
4768  // emplace_back only works for null objects or arrays
4769  if (JSON_UNLIKELY(not(is_null() or is_array())))
4770  {
4771  JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name())));
4772  }
4773 
4774  // transform null object into an array
4775  if (is_null())
4776  {
4777  m_type = value_t::array;
4778  m_value = value_t::array;
4779  assert_invariant();
4780  }
4781 
4782  // add element to array (perfect forwarding)
4783  m_value.array->emplace_back(std::forward<Args>(args)...);
4784  }
4785 
4813  template<class... Args>
4814  std::pair<iterator, bool> emplace(Args&& ... args)
4815  {
4816  // emplace only works for null objects or arrays
4817  if (JSON_UNLIKELY(not(is_null() or is_object())))
4818  {
4819  JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name())));
4820  }
4821 
4822  // transform null object into an object
4823  if (is_null())
4824  {
4825  m_type = value_t::object;
4826  m_value = value_t::object;
4827  assert_invariant();
4828  }
4829 
4830  // add element to array (perfect forwarding)
4831  auto res = m_value.object->emplace(std::forward<Args>(args)...);
4832  // create result iterator and set iterator to the result of emplace
4833  auto it = begin();
4834  it.m_it.object_iterator = res.first;
4835 
4836  // return pair of iterator and boolean
4837  return {it, res.second};
4838  }
4839 
4863  {
4864  // insert only works for arrays
4865  if (JSON_LIKELY(is_array()))
4866  {
4867  // check if iterator pos fits to this JSON value
4868  if (JSON_UNLIKELY(pos.m_object != this))
4869  {
4870  JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
4871  }
4872 
4873  // insert to array and return iterator
4874  iterator result(this);
4875  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4876  return result;
4877  }
4878 
4879  JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
4880  }
4881 
4887  {
4888  return insert(pos, val);
4889  }
4890 
4916  {
4917  // insert only works for arrays
4918  if (JSON_LIKELY(is_array()))
4919  {
4920  // check if iterator pos fits to this JSON value
4921  if (JSON_UNLIKELY(pos.m_object != this))
4922  {
4923  JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
4924  }
4925 
4926  // insert to array and return iterator
4927  iterator result(this);
4928  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4929  return result;
4930  }
4931 
4932  JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
4933  }
4934 
4966  {
4967  // insert only works for arrays
4968  if (JSON_UNLIKELY(not is_array()))
4969  {
4970  JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
4971  }
4972 
4973  // check if iterator pos fits to this JSON value
4974  if (JSON_UNLIKELY(pos.m_object != this))
4975  {
4976  JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
4977  }
4978 
4979  // check if range iterators belong to the same JSON object
4980  if (JSON_UNLIKELY(first.m_object != last.m_object))
4981  {
4982  JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
4983  }
4984 
4985  if (JSON_UNLIKELY(first.m_object == this))
4986  {
4987  JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container"));
4988  }
4989 
4990  // insert to array and return iterator
4991  iterator result(this);
4992  result.m_it.array_iterator = m_value.array->insert(
4993  pos.m_it.array_iterator,
4994  first.m_it.array_iterator,
4995  last.m_it.array_iterator);
4996  return result;
4997  }
4998 
5024  {
5025  // insert only works for arrays
5026  if (JSON_UNLIKELY(not is_array()))
5027  {
5028  JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
5029  }
5030 
5031  // check if iterator pos fits to this JSON value
5032  if (JSON_UNLIKELY(pos.m_object != this))
5033  {
5034  JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
5035  }
5036 
5037  // insert to array and return iterator
5038  iterator result(this);
5039  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist.begin(), ilist.end());
5040  return result;
5041  }
5042 
5067  {
5068  // insert only works for objects
5069  if (JSON_UNLIKELY(not is_object()))
5070  {
5071  JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
5072  }
5073 
5074  // check if range iterators belong to the same JSON object
5075  if (JSON_UNLIKELY(first.m_object != last.m_object))
5076  {
5077  JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
5078  }
5079 
5080  // passed iterators must belong to objects
5081  if (JSON_UNLIKELY(not first.m_object->is_object()))
5082  {
5083  JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
5084  }
5085 
5086  m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
5087  }
5088 
5109  {
5110  // implicitly convert null value to an empty object
5111  if (is_null())
5112  {
5113  m_type = value_t::object;
5114  m_value.object = create<object_t>();
5115  assert_invariant();
5116  }
5117 
5118  if (JSON_UNLIKELY(not is_object()))
5119  {
5120  JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
5121  }
5122  if (JSON_UNLIKELY(not j.is_object()))
5123  {
5124  JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name())));
5125  }
5126 
5127  for (auto it = j.cbegin(); it != j.cend(); ++it)
5128  {
5129  m_value.object->operator[](it.key()) = it.value();
5130  }
5131  }
5132 
5160  {
5161  // implicitly convert null value to an empty object
5162  if (is_null())
5163  {
5164  m_type = value_t::object;
5165  m_value.object = create<object_t>();
5166  assert_invariant();
5167  }
5168 
5169  if (JSON_UNLIKELY(not is_object()))
5170  {
5171  JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
5172  }
5173 
5174  // check if range iterators belong to the same JSON object
5175  if (JSON_UNLIKELY(first.m_object != last.m_object))
5176  {
5177  JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
5178  }
5179 
5180  // passed iterators must belong to objects
5181  if (JSON_UNLIKELY(not first.m_object->is_object()
5182  or not first.m_object->is_object()))
5183  {
5184  JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
5185  }
5186 
5187  for (auto it = first; it != last; ++it)
5188  {
5189  m_value.object->operator[](it.key()) = it.value();
5190  }
5191  }
5192 
5210  void swap(reference other) noexcept (
5211  std::is_nothrow_move_constructible<value_t>::value and
5212  std::is_nothrow_move_assignable<value_t>::value and
5213  std::is_nothrow_move_constructible<json_value>::value and
5214  std::is_nothrow_move_assignable<json_value>::value
5215  )
5216  {
5217  std::swap(m_type, other.m_type);
5218  std::swap(m_value, other.m_value);
5219  assert_invariant();
5220  }
5221 
5242  void swap(array_t& other)
5243  {
5244  // swap only works for arrays
5245  if (JSON_LIKELY(is_array()))
5246  {
5247  std::swap(*(m_value.array), other);
5248  }
5249  else
5250  {
5251  JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
5252  }
5253  }
5254 
5275  void swap(object_t& other)
5276  {
5277  // swap only works for objects
5278  if (JSON_LIKELY(is_object()))
5279  {
5280  std::swap(*(m_value.object), other);
5281  }
5282  else
5283  {
5284  JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
5285  }
5286  }
5287 
5308  void swap(string_t& other)
5309  {
5310  // swap only works for strings
5311  if (JSON_LIKELY(is_string()))
5312  {
5313  std::swap(*(m_value.string), other);
5314  }
5315  else
5316  {
5317  JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
5318  }
5319  }
5320 
5322 
5323  public:
5325  // lexicographical comparison operators //
5327 
5330 
5370  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5371  {
5372  const auto lhs_type = lhs.type();
5373  const auto rhs_type = rhs.type();
5374 
5375  if (lhs_type == rhs_type)
5376  {
5377  switch (lhs_type)
5378  {
5379  case value_t::array:
5380  return (*lhs.m_value.array == *rhs.m_value.array);
5381 
5382  case value_t::object:
5383  return (*lhs.m_value.object == *rhs.m_value.object);
5384 
5385  case value_t::null:
5386  return true;
5387 
5388  case value_t::string:
5389  return (*lhs.m_value.string == *rhs.m_value.string);
5390 
5391  case value_t::boolean:
5392  return (lhs.m_value.boolean == rhs.m_value.boolean);
5393 
5395  return (lhs.m_value.number_integer == rhs.m_value.number_integer);
5396 
5398  return (lhs.m_value.number_unsigned == rhs.m_value.number_unsigned);
5399 
5400  case value_t::number_float:
5401  return (lhs.m_value.number_float == rhs.m_value.number_float);
5402 
5403  default:
5404  return false;
5405  }
5406  }
5407  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5408  {
5409  return (static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float);
5410  }
5411  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5412  {
5413  return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer));
5414  }
5415  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5416  {
5417  return (static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float);
5418  }
5419  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5420  {
5421  return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned));
5422  }
5423  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5424  {
5425  return (static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer);
5426  }
5427  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5428  {
5429  return (lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned));
5430  }
5431 
5432  return false;
5433  }
5434 
5439  template<typename ScalarType, typename std::enable_if<
5440  std::is_scalar<ScalarType>::value, int>::type = 0>
5441  friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
5442  {
5443  return (lhs == basic_json(rhs));
5444  }
5445 
5450  template<typename ScalarType, typename std::enable_if<
5451  std::is_scalar<ScalarType>::value, int>::type = 0>
5452  friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
5453  {
5454  return (basic_json(lhs) == rhs);
5455  }
5456 
5475  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5476  {
5477  return not (lhs == rhs);
5478  }
5479 
5484  template<typename ScalarType, typename std::enable_if<
5485  std::is_scalar<ScalarType>::value, int>::type = 0>
5486  friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
5487  {
5488  return (lhs != basic_json(rhs));
5489  }
5490 
5495  template<typename ScalarType, typename std::enable_if<
5496  std::is_scalar<ScalarType>::value, int>::type = 0>
5497  friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
5498  {
5499  return (basic_json(lhs) != rhs);
5500  }
5501 
5528  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5529  {
5530  const auto lhs_type = lhs.type();
5531  const auto rhs_type = rhs.type();
5532 
5533  if (lhs_type == rhs_type)
5534  {
5535  switch (lhs_type)
5536  {
5537  case value_t::array:
5538  return (*lhs.m_value.array) < (*rhs.m_value.array);
5539 
5540  case value_t::object:
5541  return *lhs.m_value.object < *rhs.m_value.object;
5542 
5543  case value_t::null:
5544  return false;
5545 
5546  case value_t::string:
5547  return *lhs.m_value.string < *rhs.m_value.string;
5548 
5549  case value_t::boolean:
5550  return lhs.m_value.boolean < rhs.m_value.boolean;
5551 
5553  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5554 
5556  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5557 
5558  case value_t::number_float:
5559  return lhs.m_value.number_float < rhs.m_value.number_float;
5560 
5561  default:
5562  return false;
5563  }
5564  }
5565  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5566  {
5567  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5568  }
5569  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5570  {
5571  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
5572  }
5573  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5574  {
5575  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5576  }
5577  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5578  {
5579  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
5580  }
5581  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5582  {
5583  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5584  }
5585  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5586  {
5587  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5588  }
5589 
5590  // We only reach this line if we cannot compare values. In that case,
5591  // we compare types. Note we have to call the operator explicitly,
5592  // because MSVC has problems otherwise.
5593  return operator<(lhs_type, rhs_type);
5594  }
5595 
5600  template<typename ScalarType, typename std::enable_if<
5601  std::is_scalar<ScalarType>::value, int>::type = 0>
5602  friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
5603  {
5604  return (lhs < basic_json(rhs));
5605  }
5606 
5611  template<typename ScalarType, typename std::enable_if<
5612  std::is_scalar<ScalarType>::value, int>::type = 0>
5613  friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
5614  {
5615  return (basic_json(lhs) < rhs);
5616  }
5617 
5637  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5638  {
5639  return not (rhs < lhs);
5640  }
5641 
5646  template<typename ScalarType, typename std::enable_if<
5647  std::is_scalar<ScalarType>::value, int>::type = 0>
5648  friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
5649  {
5650  return (lhs <= basic_json(rhs));
5651  }
5652 
5657  template<typename ScalarType, typename std::enable_if<
5658  std::is_scalar<ScalarType>::value, int>::type = 0>
5659  friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
5660  {
5661  return (basic_json(lhs) <= rhs);
5662  }
5663 
5683  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5684  {
5685  return not (lhs <= rhs);
5686  }
5687 
5692  template<typename ScalarType, typename std::enable_if<
5693  std::is_scalar<ScalarType>::value, int>::type = 0>
5694  friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
5695  {
5696  return (lhs > basic_json(rhs));
5697  }
5698 
5703  template<typename ScalarType, typename std::enable_if<
5704  std::is_scalar<ScalarType>::value, int>::type = 0>
5705  friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
5706  {
5707  return (basic_json(lhs) > rhs);
5708  }
5709 
5729  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5730  {
5731  return not (lhs < rhs);
5732  }
5733 
5738  template<typename ScalarType, typename std::enable_if<
5739  std::is_scalar<ScalarType>::value, int>::type = 0>
5740  friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
5741  {
5742  return (lhs >= basic_json(rhs));
5743  }
5744 
5749  template<typename ScalarType, typename std::enable_if<
5750  std::is_scalar<ScalarType>::value, int>::type = 0>
5751  friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
5752  {
5753  return (basic_json(lhs) >= rhs);
5754  }
5755 
5757 
5759  // serialization //
5761 
5764 
5796  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5797  {
5798  // read width member and use it as indentation parameter if nonzero
5799  const bool pretty_print = (o.width() > 0);
5800  const auto indentation = (pretty_print ? o.width() : 0);
5801 
5802  // reset width to 0 for subsequent calls to this stream
5803  o.width(0);
5804 
5805  // do the actual serialization
5806  serializer s(detail::output_adapter<char>(o), o.fill());
5807  s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
5808  return o;
5809  }
5810 
5819  JSON_DEPRECATED
5820  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5821  {
5822  return o << j;
5823  }
5824 
5826 
5827 
5829  // deserialization //
5831 
5834 
5898  const parser_callback_t cb = nullptr,
5899  const bool allow_exceptions = true)
5900  {
5901  basic_json result;
5902  parser(i, cb, allow_exceptions).parse(true, result);
5903  return result;
5904  }
5905 
5910  const parser_callback_t cb = nullptr,
5911  const bool allow_exceptions = true)
5912  {
5913  basic_json result;
5914  parser(i, cb, allow_exceptions).parse(true, result);
5915  return result;
5916  }
5917 
5918  static bool accept(detail::input_adapter i)
5919  {
5920  return parser(i).accept(true);
5921  }
5922 
5923  static bool accept(detail::input_adapter& i)
5924  {
5925  return parser(i).accept(true);
5926  }
5927 
5975  template<class IteratorType, typename std::enable_if<
5976  std::is_base_of<
5977  std::random_access_iterator_tag,
5978  typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
5979  static basic_json parse(IteratorType first, IteratorType last,
5980  const parser_callback_t cb = nullptr,
5981  const bool allow_exceptions = true)
5982  {
5983  basic_json result;
5984  parser(detail::input_adapter(first, last), cb, allow_exceptions).parse(true, result);
5985  return result;
5986  }
5987 
5988  template<class IteratorType, typename std::enable_if<
5989  std::is_base_of<
5990  std::random_access_iterator_tag,
5991  typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
5992  static bool accept(IteratorType first, IteratorType last)
5993  {
5994  return parser(detail::input_adapter(first, last)).accept(true);
5995  }
5996 
6005  JSON_DEPRECATED
6006  friend std::istream& operator<<(basic_json& j, std::istream& i)
6007  {
6008  return operator>>(i, j);
6009  }
6010 
6036  friend std::istream& operator>>(std::istream& i, basic_json& j)
6037  {
6038  parser(detail::input_adapter(i)).parse(false, j);
6039  return i;
6040  }
6041 
6043 
6045  // convenience functions //
6047 
6078  const char* type_name() const noexcept
6079  {
6080  {
6081  switch (m_type)
6082  {
6083  case value_t::null:
6084  return "null";
6085  case value_t::object:
6086  return "object";
6087  case value_t::array:
6088  return "array";
6089  case value_t::string:
6090  return "string";
6091  case value_t::boolean:
6092  return "boolean";
6093  case value_t::discarded:
6094  return "discarded";
6095  default:
6096  return "number";
6097  }
6098  }
6099  }
6100 
6101 
6102  private:
6104  // member variables //
6106 
6108  value_t m_type = value_t::null;
6109 
6111  json_value m_value = {};
6112 
6114  // binary serialization/deserialization //
6116 
6119 
6120  public:
6209  static std::vector<uint8_t> to_cbor(const basic_json& j)
6210  {
6211  std::vector<uint8_t> result;
6212  to_cbor(j, result);
6213  return result;
6214  }
6215 
6216  static void to_cbor(const basic_json& j, detail::output_adapter<uint8_t> o)
6217  {
6218  binary_writer<uint8_t>(o).write_cbor(j);
6219  }
6220 
6221  static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
6222  {
6223  binary_writer<char>(o).write_cbor(j);
6224  }
6225 
6306  static std::vector<uint8_t> to_msgpack(const basic_json& j)
6307  {
6308  std::vector<uint8_t> result;
6309  to_msgpack(j, result);
6310  return result;
6311  }
6312 
6313  static void to_msgpack(const basic_json& j, detail::output_adapter<uint8_t> o)
6314  {
6315  binary_writer<uint8_t>(o).write_msgpack(j);
6316  }
6317 
6318  static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
6319  {
6320  binary_writer<char>(o).write_msgpack(j);
6321  }
6322 
6403  static std::vector<uint8_t> to_ubjson(const basic_json& j,
6404  const bool use_size = false,
6405  const bool use_type = false)
6406  {
6407  std::vector<uint8_t> result;
6408  to_ubjson(j, result, use_size, use_type);
6409  return result;
6410  }
6411 
6412  static void to_ubjson(const basic_json& j, detail::output_adapter<uint8_t> o,
6413  const bool use_size = false, const bool use_type = false)
6414  {
6415  binary_writer<uint8_t>(o).write_ubjson(j, use_size, use_type);
6416  }
6417 
6418  static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
6419  const bool use_size = false, const bool use_type = false)
6420  {
6421  binary_writer<char>(o).write_ubjson(j, use_size, use_type);
6422  }
6423 
6518  const bool strict = true)
6519  {
6520  return binary_reader(i).parse_cbor(strict);
6521  }
6522 
6526  template<typename A1, typename A2,
6527  detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
6528  static basic_json from_cbor(A1 && a1, A2 && a2, const bool strict = true)
6529  {
6530  return binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).parse_cbor(strict);
6531  }
6532 
6607  const bool strict = true)
6608  {
6609  return binary_reader(i).parse_msgpack(strict);
6610  }
6611 
6615  template<typename A1, typename A2,
6616  detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
6617  static basic_json from_msgpack(A1 && a1, A2 && a2, const bool strict = true)
6618  {
6619  return binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).parse_msgpack(strict);
6620  }
6621 
6676  const bool strict = true)
6677  {
6678  return binary_reader(i).parse_ubjson(strict);
6679  }
6680 
6681  template<typename A1, typename A2,
6682  detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
6683  static basic_json from_ubjson(A1 && a1, A2 && a2, const bool strict = true)
6684  {
6685  return binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).parse_ubjson(strict);
6686  }
6687 
6689 
6691  // JSON Pointer support //
6693 
6696 
6731  {
6732  return ptr.get_unchecked(this);
6733  }
6734 
6759  {
6760  return ptr.get_unchecked(this);
6761  }
6762 
6802  {
6803  return ptr.get_checked(this);
6804  }
6805 
6844  const_reference at(const json_pointer& ptr) const
6845  {
6846  return ptr.get_checked(this);
6847  }
6848 
6872  {
6873  basic_json result(value_t::object);
6874  json_pointer::flatten("", *this, result);
6875  return result;
6876  }
6877 
6909  {
6910  return json_pointer::unflatten(*this);
6911  }
6912 
6914 
6916  // JSON Patch functions //
6918 
6921 
6969  basic_json patch(const basic_json& json_patch) const
6970  {
6971  // make a working copy to apply the patch to
6972  basic_json result = *this;
6973 
6974  // the valid JSON Patch operations
6975  enum class patch_operations {add, remove, replace, move, copy, test, invalid};
6976 
6977  const auto get_op = [](const std::string & op)
6978  {
6979  if (op == "add")
6980  {
6981  return patch_operations::add;
6982  }
6983  if (op == "remove")
6984  {
6985  return patch_operations::remove;
6986  }
6987  if (op == "replace")
6988  {
6989  return patch_operations::replace;
6990  }
6991  if (op == "move")
6992  {
6993  return patch_operations::move;
6994  }
6995  if (op == "copy")
6996  {
6997  return patch_operations::copy;
6998  }
6999  if (op == "test")
7000  {
7001  return patch_operations::test;
7002  }
7003 
7004  return patch_operations::invalid;
7005  };
7006 
7007  // wrapper for "add" operation; add value at ptr
7008  const auto operation_add = [&result](json_pointer & ptr, basic_json val)
7009  {
7010  // adding to the root of the target document means replacing it
7011  if (ptr.is_root())
7012  {
7013  result = val;
7014  }
7015  else
7016  {
7017  // make sure the top element of the pointer exists
7018  json_pointer top_pointer = ptr.top();
7019  if (top_pointer != ptr)
7020  {
7021  result.at(top_pointer);
7022  }
7023 
7024  // get reference to parent of JSON pointer ptr
7025  const auto last_path = ptr.pop_back();
7026  basic_json& parent = result[ptr];
7027 
7028  switch (parent.m_type)
7029  {
7030  case value_t::null:
7031  case value_t::object:
7032  {
7033  // use operator[] to add value
7034  parent[last_path] = val;
7035  break;
7036  }
7037 
7038  case value_t::array:
7039  {
7040  if (last_path == "-")
7041  {
7042  // special case: append to back
7043  parent.push_back(val);
7044  }
7045  else
7046  {
7047  const auto idx = json_pointer::array_index(last_path);
7048  if (JSON_UNLIKELY(static_cast<size_type>(idx) > parent.size()))
7049  {
7050  // avoid undefined behavior
7051  JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
7052  }
7053  else
7054  {
7055  // default case: insert add offset
7056  parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
7057  }
7058  }
7059  break;
7060  }
7061 
7062  default:
7063  {
7064  // if there exists a parent it cannot be primitive
7065  assert(false); // LCOV_EXCL_LINE
7066  }
7067  }
7068  }
7069  };
7070 
7071  // wrapper for "remove" operation; remove value at ptr
7072  const auto operation_remove = [&result](json_pointer & ptr)
7073  {
7074  // get reference to parent of JSON pointer ptr
7075  const auto last_path = ptr.pop_back();
7076  basic_json& parent = result.at(ptr);
7077 
7078  // remove child
7079  if (parent.is_object())
7080  {
7081  // perform range check
7082  auto it = parent.find(last_path);
7083  if (JSON_LIKELY(it != parent.end()))
7084  {
7085  parent.erase(it);
7086  }
7087  else
7088  {
7089  JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found"));
7090  }
7091  }
7092  else if (parent.is_array())
7093  {
7094  // note erase performs range check
7095  parent.erase(static_cast<size_type>(json_pointer::array_index(last_path)));
7096  }
7097  };
7098 
7099  // type check: top level value must be an array
7100  if (JSON_UNLIKELY(not json_patch.is_array()))
7101  {
7102  JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
7103  }
7104 
7105  // iterate and apply the operations
7106  for (const auto& val : json_patch)
7107  {
7108  // wrapper to get a value for an operation
7109  const auto get_value = [&val](const std::string & op,
7110  const std::string & member,
7111  bool string_type) -> basic_json &
7112  {
7113  // find value
7114  auto it = val.m_value.object->find(member);
7115 
7116  // context-sensitive error message
7117  const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
7118 
7119  // check if desired value is present
7120  if (JSON_UNLIKELY(it == val.m_value.object->end()))
7121  {
7122  JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'"));
7123  }
7124 
7125  // check if result is of type string
7126  if (JSON_UNLIKELY(string_type and not it->second.is_string()))
7127  {
7128  JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'"));
7129  }
7130 
7131  // no error: return value
7132  return it->second;
7133  };
7134 
7135  // type check: every element of the array must be an object
7136  if (JSON_UNLIKELY(not val.is_object()))
7137  {
7138  JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
7139  }
7140 
7141  // collect mandatory members
7142  const std::string op = get_value("op", "op", true);
7143  const std::string path = get_value(op, "path", true);
7144  json_pointer ptr(path);
7145 
7146  switch (get_op(op))
7147  {
7148  case patch_operations::add:
7149  {
7150  operation_add(ptr, get_value("add", "value", false));
7151  break;
7152  }
7153 
7154  case patch_operations::remove:
7155  {
7156  operation_remove(ptr);
7157  break;
7158  }
7159 
7160  case patch_operations::replace:
7161  {
7162  // the "path" location must exist - use at()
7163  result.at(ptr) = get_value("replace", "value", false);
7164  break;
7165  }
7166 
7167  case patch_operations::move:
7168  {
7169  const std::string from_path = get_value("move", "from", true);
7170  json_pointer from_ptr(from_path);
7171 
7172  // the "from" location must exist - use at()
7173  basic_json v = result.at(from_ptr);
7174 
7175  // The move operation is functionally identical to a
7176  // "remove" operation on the "from" location, followed
7177  // immediately by an "add" operation at the target
7178  // location with the value that was just removed.
7179  operation_remove(from_ptr);
7180  operation_add(ptr, v);
7181  break;
7182  }
7183 
7184  case patch_operations::copy:
7185  {
7186  const std::string from_path = get_value("copy", "from", true);
7187  const json_pointer from_ptr(from_path);
7188 
7189  // the "from" location must exist - use at()
7190  basic_json v = result.at(from_ptr);
7191 
7192  // The copy is functionally identical to an "add"
7193  // operation at the target location using the value
7194  // specified in the "from" member.
7195  operation_add(ptr, v);
7196  break;
7197  }
7198 
7199  case patch_operations::test:
7200  {
7201  bool success = false;
7202  JSON_TRY
7203  {
7204  // check if "value" matches the one at "path"
7205  // the "path" location must exist - use at()
7206  success = (result.at(ptr) == get_value("test", "value", false));
7207  }
7208  JSON_CATCH (out_of_range&)
7209  {
7210  // ignore out of range errors: success remains false
7211  }
7212 
7213  // throw an exception if test fails
7214  if (JSON_UNLIKELY(not success))
7215  {
7216  JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump()));
7217  }
7218 
7219  break;
7220  }
7221 
7222  case patch_operations::invalid:
7223  {
7224  // op must be "add", "remove", "replace", "move", "copy", or
7225  // "test"
7226  JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid"));
7227  }
7228  }
7229  }
7230 
7231  return result;
7232  }
7233 
7267  static basic_json diff(const basic_json& source, const basic_json& target,
7268  const std::string& path = "")
7269  {
7270  // the patch
7271  basic_json result(value_t::array);
7272 
7273  // if the values are the same, return empty patch
7274  if (source == target)
7275  {
7276  return result;
7277  }
7278 
7279  if (source.type() != target.type())
7280  {
7281  // different types: replace value
7282  result.push_back(
7283  {
7284  {"op", "replace"}, {"path", path}, {"value", target}
7285  });
7286  }
7287  else
7288  {
7289  switch (source.type())
7290  {
7291  case value_t::array:
7292  {
7293  // first pass: traverse common elements
7294  std::size_t i = 0;
7295  while (i < source.size() and i < target.size())
7296  {
7297  // recursive call to compare array values at index i
7298  auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
7299  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
7300  ++i;
7301  }
7302 
7303  // i now reached the end of at least one array
7304  // in a second pass, traverse the remaining elements
7305 
7306  // remove my remaining elements
7307  const auto end_index = static_cast<difference_type>(result.size());
7308  while (i < source.size())
7309  {
7310  // add operations in reverse order to avoid invalid
7311  // indices
7312  result.insert(result.begin() + end_index, object(
7313  {
7314  {"op", "remove"},
7315  {"path", path + "/" + std::to_string(i)}
7316  }));
7317  ++i;
7318  }
7319 
7320  // add other remaining elements
7321  while (i < target.size())
7322  {
7323  result.push_back(
7324  {
7325  {"op", "add"},
7326  {"path", path + "/" + std::to_string(i)},
7327  {"value", target[i]}
7328  });
7329  ++i;
7330  }
7331 
7332  break;
7333  }
7334 
7335  case value_t::object:
7336  {
7337  // first pass: traverse this object's elements
7338  for (auto it = source.cbegin(); it != source.cend(); ++it)
7339  {
7340  // escape the key name to be used in a JSON patch
7341  const auto key = json_pointer::escape(it.key());
7342 
7343  if (target.find(it.key()) != target.end())
7344  {
7345  // recursive call to compare object values at key it
7346  auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
7347  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
7348  }
7349  else
7350  {
7351  // found a key that is not in o -> remove it
7352  result.push_back(object(
7353  {
7354  {"op", "remove"}, {"path", path + "/" + key}
7355  }));
7356  }
7357  }
7358 
7359  // second pass: traverse other object's elements
7360  for (auto it = target.cbegin(); it != target.cend(); ++it)
7361  {
7362  if (source.find(it.key()) == source.end())
7363  {
7364  // found a key that is not in this -> add it
7365  const auto key = json_pointer::escape(it.key());
7366  result.push_back(
7367  {
7368  {"op", "add"}, {"path", path + "/" + key},
7369  {"value", it.value()}
7370  });
7371  }
7372  }
7373 
7374  break;
7375  }
7376 
7377  default:
7378  {
7379  // both primitive type: replace value
7380  result.push_back(
7381  {
7382  {"op", "replace"}, {"path", path}, {"value", target}
7383  });
7384  break;
7385  }
7386  }
7387  }
7388 
7389  return result;
7390  }
7391 
7393 
7395  // JSON Merge Patch functions //
7397 
7400 
7444  {
7445  if (patch.is_object())
7446  {
7447  if (not is_object())
7448  {
7449  *this = object();
7450  }
7451  for (auto it = patch.begin(); it != patch.end(); ++it)
7452  {
7453  if (it.value().is_null())
7454  {
7455  erase(it.key());
7456  }
7457  else
7458  {
7459  operator[](it.key()).merge_patch(it.value());
7460  }
7461  }
7462  }
7463  else
7464  {
7465  *this = patch;
7466  }
7467  }
7468 
7470 };
7471 } // namespace nlohmann
7472 
7474 // nonmember support //
7476 
7477 // specialization of std::swap, and std::hash
7478 namespace std
7479 {
7485 template<>
7486 inline void swap(nlohmann::json& j1,
7487  nlohmann::json& j2) noexcept(
7488  is_nothrow_move_constructible<nlohmann::json>::value and
7489  is_nothrow_move_assignable<nlohmann::json>::value
7490  )
7491 {
7492  j1.swap(j2);
7493 }
7494 
7496 template<>
7497 struct hash<nlohmann::json>
7498 {
7504  std::size_t operator()(const nlohmann::json& j) const
7505  {
7506  // a naive hashing via the string representation
7507  const auto& h = hash<nlohmann::json::string_t>();
7508  return h(j.dump());
7509  }
7510 };
7511 
7515 template<>
7517 {
7523  nlohmann::detail::value_t rhs) const noexcept
7524  {
7525  return nlohmann::detail::operator<(lhs, rhs);
7526  }
7527 };
7528 
7529 } // namespace std
7530 
7544 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
7545 {
7546  return nlohmann::json::parse(s, s + n);
7547 }
7548 
7562 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
7563 {
7564  return nlohmann::json::json_pointer(std::string(s, n));
7565 }
7566 
7567 #include <nlohmann/detail/macro_unscope.hpp>
7568 
7569 #endif
nlohmann::detail::json_reverse_iterator
a template for a reverse iterator class
Definition: json_reverse_iterator.hpp:34
nlohmann::basic_json::insert
void insert(const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:5066
nlohmann::basic_json::erase
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition: json.hpp:3489
nlohmann::basic_json::number_float_t
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:804
nlohmann::detail::type_error
exception indicating executing a member function with a wrong type
Definition: exceptions.hpp:235
nlohmann::basic_json::operator[]
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition: json.hpp:6758
nlohmann::basic_json::insert
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:4915
nlohmann::detail::exception
general exception of the basic_json class
Definition: exceptions.hpp:43
nlohmann::detail::value_t
value_t
the JSON type enumeration
Definition: value_t.hpp:40
nlohmann::basic_json::at
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:2822
nlohmann::basic_json::is_number_integer
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2083
nlohmann::basic_json::object
static basic_json object(initializer_list_t init={})
explicitly create an object from an initializer list
Definition: json.hpp:1451
nlohmann::basic_json::front
reference front()
access the first element
Definition: json.hpp:3378
nlohmann::basic_json::array_t
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
Definition: json.hpp:514
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:1319
nlohmann::basic_json::operator!=
friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5497
nlohmann::basic_json::operator<
friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
comparison: less than
Definition: json.hpp:5602
nlohmann::detail::value_t::object
object (unordered set of name/value pairs)
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:77
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:6306
nlohmann::basic_json::operator[]
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition: json.hpp:6730
nlohmann::basic_json::operator[]
reference operator[](T *key)
access specified object element
Definition: json.hpp:3143
nlohmann::basic_json::find
const_iterator find(KeyT &&key) const
find an element in a JSON object
Definition: json.hpp:3784
nlohmann::detail::binary_reader::parse_ubjson
BasicJsonType parse_ubjson(const bool strict)
create a JSON value from UBJSON input
Definition: binary_reader.hpp:104
nlohmann::basic_json::basic_json
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:1750
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:3818
nlohmann::basic_json::cend
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:3969
nlohmann::basic_json::operator<<
JSON_DEPRECATED friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:6006
nlohmann::basic_json::operator+=
reference operator+=(initializer_list_t init)
add an object to an object
Definition: json.hpp:4738
nlohmann::basic_json::begin
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:3868
nlohmann::basic_json::from_msgpack
static basic_json from_msgpack(detail::input_adapter i, const bool strict=true)
create a JSON value from an input in MessagePack format
Definition: json.hpp:6606
nlohmann::basic_json::is_null
constexpr bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2002
libzip::source
std::function< struct zip_source *(struct zip *)> source
Source creation for adding files.
Definition: zip.hpp:122
nlohmann::detail::out_of_range
exception indicating access out of the defined range
Definition: exceptions.hpp:279
nlohmann::basic_json::at
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition: json.hpp:6844
nlohmann::detail::invalid_iterator
exception indicating errors with iterators
Definition: exceptions.hpp:183
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:5210
nlohmann::basic_json::meta
static basic_json meta()
returns version information on the library
Definition: json.hpp:308
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:267
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:3681
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:2970
nlohmann::basic_json::size_type
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:252
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:2462
nlohmann::basic_json::basic_json
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1543
nlohmann::basic_json::get
ValueType get() const noexcept(noexcept(JSONSerializer< ValueTypeCV >::from_json(std::declval< const basic_json_t & >())))
get a value (explicit); special case
Definition: json.hpp:2513
nlohmann
namespace for Niels Lohmann
Definition: adl_serializer.hpp:8
nlohmann::detail::binary_writer
serialization to CBOR and MessagePack values
Definition: binary_writer.hpp:24
nlohmann::basic_json::swap
void swap(object_t &other)
exchanges the values
Definition: json.hpp:5275
nlohmann::basic_json::is_primitive
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:1953
nlohmann::detail::value_t::number_float
number value (floating-point)
nlohmann::basic_json::find
iterator find(KeyT &&key)
find an element in a JSON object
Definition: json.hpp:3767
nlohmann::json_pointer
JSON Pointer.
Definition: json_pointer.hpp:15
nlohmann::detail::other_error
exception indicating other library errors
Definition: exceptions.hpp:316
nlohmann::basic_json::operator=
reference & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value)
copy assignment
Definition: json.hpp:1787
nlohmann::basic_json::boolean_t
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:593
nlohmann::detail::value_t::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:5108
nlohmann::basic_json::parse
static 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:5897
nlohmann::basic_json::operator<=
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5637
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:5159
nlohmann::basic_json::is_boolean
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2024
nlohmann::basic_json::items
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
Definition: json.hpp:4240
nlohmann::basic_json::begin
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:3858
nlohmann::basic_json::push_back
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4615
nlohmann::detail::binary_reader::parse_cbor
BasicJsonType parse_cbor(const bool strict)
create a JSON value from CBOR input
Definition: binary_reader.hpp:62
nlohmann::basic_json::difference_type
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:250
nlohmann::basic_json::iterator_wrapper
static JSON_DEPRECATED iteration_proxy< iterator > iterator_wrapper(reference ref) noexcept
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4166
nlohmann::basic_json::rend
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4044
nlohmann::basic_json::empty
bool empty() const noexcept
checks whether the container is empty.
Definition: json.hpp:4296
nlohmann::basic_json::get_ptr
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:2624
nlohmann::detail::lexer
lexical analysis
Definition: lexer.hpp:30
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:468
nlohmann::basic_json::type_name
const char * type_name() const noexcept
return the type as string
Definition: json.hpp:6078
nlohmann::detail::json_ref
Definition: json_ref.hpp:11
nlohmann::basic_json::value
string_t value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
Definition: json.hpp:3348
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:1237
nlohmann::detail::parse_error
exception indicating a parse error
Definition: exceptions.hpp:111
nlohmann::basic_json::operator==
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5370
nlohmann::basic_json::operator>
friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5705
nlohmann::detail::iter_impl
a template for a bidirectional iterator for the basic_json class
Definition: iter_impl.hpp:42
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 value
nlohmann::basic_json::is_string
constexpr bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2205
nlohmann::detail::parse_error::create
static parse_error create(int id_, std::size_t byte_, const std::string &what_arg)
create a parse error exception
Definition: exceptions.hpp:122
nlohmann::basic_json::get
basic_json get() const
get special-case overload
Definition: json.hpp:2412
nlohmann::basic_json::is_discarded
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2232
nlohmann::basic_json::basic_json
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1667
nlohmann::basic_json::is_number_float
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2139
nlohmann::basic_json::operator<=
friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5659
nlohmann::basic_json::is_structured
constexpr bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:1980
nlohmann::basic_json::operator>
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5683
nlohmann::basic_json::crend
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4102
nlohmann::basic_json::operator>
friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
comparison: greater than
Definition: json.hpp:5694
nlohmann::detail::binary_reader::parse_msgpack
BasicJsonType parse_msgpack(const bool strict)
create a JSON value from MessagePack input
Definition: binary_reader.hpp:83
nlohmann::basic_json::clear
void clear() noexcept
clears the contents
Definition: json.hpp:4508
nlohmann::basic_json::get_allocator
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:277
nlohmann::basic_json::operator>>
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:6036
nlohmann::basic_json::rbegin
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4007
nlohmann::detail::parser
syntax analysis
Definition: parser.hpp:30
nlohmann::basic_json::operator[]
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3016
nlohmann::basic_json::push_back
void push_back(initializer_list_t init)
add an object to an object
Definition: json.hpp:4720
nlohmann::basic_json::~basic_json
~basic_json() noexcept
destructor
Definition: json.hpp:1820
nlohmann::basic_json::flatten
basic_json flatten() const
return flattened JSON value
Definition: json.hpp:6871
nlohmann::basic_json::end
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.hpp:3929
nlohmann::basic_json::operator+=
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4689
nlohmann::basic_json::get
constexpr const PointerType get() const noexcept
get a pointer value (explicit)
Definition: json.hpp:2562
nlohmann::basic_json::get
PointerType get() noexcept
get a pointer value (explicit)
Definition: json.hpp:2550
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:7522
nlohmann::basic_json::number_unsigned_t
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:736
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:5979
nlohmann::detail::output_adapter_t
std::shared_ptr< output_adapter_protocol< CharType > > output_adapter_t
a type to simplify interfaces
Definition: output_adapters.hpp:26
nlohmann::detail::operator<
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: value_t.hpp:63
nlohmann::basic_json::operator==
friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5452
nlohmann::basic_json::is_number_unsigned
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2111
nlohmann::basic_json::from_cbor
static basic_json from_cbor(A1 &&a1, A2 &&a2, const bool strict=true)
create a JSON value from an input in CBOR format
Definition: json.hpp:6528
nlohmann::basic_json::back
reference back()
access the last element
Definition: json.hpp:3422
nlohmann::basic_json::at
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:2775
nlohmann::basic_json::is_object
constexpr bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2161
nlohmann::basic_json::basic_json
basic_json(const value_t v)
create an empty value with a given type
Definition: json.hpp:1147
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:6209
nlohmann::basic_json::unflatten
basic_json unflatten() const
unflatten a previously flattened JSON value
Definition: json.hpp:6908
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:3277
nlohmann::basic_json::insert
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4886
nlohmann::basic_json::erase
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:3716
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:269
nlohmann::basic_json::string_t
StringType string_t
a type for a string
Definition: json.hpp:567
nlohmann::basic_json::operator>=
friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5740
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:1478
nlohmann::detail::external_constructor
Definition: to_json.hpp:22
nlohmann::basic_json::rend
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.hpp:4036
nlohmann::basic_json::get_ref
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:2673
nlohmann::basic_json::is_number
constexpr bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2054
nlohmann::basic_json::crbegin
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4073
nlohmann::detail::value_t::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:206
nlohmann::detail::is_compatible_type
Definition: meta.hpp:242
nlohmann::detail::binary_reader
deserialization of CBOR and MessagePack values
Definition: binary_reader.hpp:35
nlohmann::detail::value_t::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:2873
nlohmann::basic_json::push_back
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4579
nlohmann::basic_json::size
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4368
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:6403
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:2924
nlohmann::detail::parser::parse_event_t
parse_event_t
Definition: parser.hpp:39
nlohmann::detail::primitive_iterator_t
Definition: primitive_iterator.hpp:19
nlohmann::detail::value_t::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:4814
nlohmann::basic_json::operator>=
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5729
nlohmann::basic_json::insert
iterator insert(const_iterator pos, initializer_list_t ilist)
inserts elements
Definition: json.hpp:5023
nlohmann::detail::serializer
Definition: serializer.hpp:35
nlohmann::basic_json::erase
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition: json.hpp:3594
nlohmann::basic_json::allocator_type
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:255
nlohmann::basic_json::operator<
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5528
nlohmann::basic_json
a class to store JSON values
Definition: json.hpp:161
nlohmann::basic_json::parse
static basic_json parse(detail::input_adapter &i, const parser_callback_t cb=nullptr, const bool allow_exceptions=true)
create an empty value with a given type parse(detail::input_adapter, const parser_callback_t)
Definition: json.hpp:5909
nlohmann::basic_json::operator==
friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
comparison: equal
Definition: json.hpp:5441
nlohmann::basic_json::operator>>
JSON_DEPRECATED friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5820
nlohmann::basic_json::array
static basic_json array(initializer_list_t init={})
explicitly create an array from an initializer list
Definition: json.hpp:1408
nlohmann::detail::input_adapter
Definition: input_adapters.hpp:168
nlohmann::basic_json::operator!=
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5475
nlohmann::basic_json::dump
string_t dump(const int indent=-1, const char indent_char=' ', const bool ensure_ascii=false) const
serialization
Definition: json.hpp:1873
nlohmann::basic_json::operator[]
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:3103
nlohmann::basic_json::from_msgpack
static basic_json from_msgpack(A1 &&a1, A2 &&a2, const bool strict=true)
create a JSON value from an input in MessagePack format
Definition: json.hpp:6617
nlohmann::basic_json::diff
static 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:7267
nlohmann::basic_json::emplace_back
void emplace_back(Args &&... args)
add an object to an array
Definition: json.hpp:4766
nlohmann::basic_json::swap
void swap(array_t &other)
exchanges the values
Definition: json.hpp:5242
nlohmann::basic_json::json_pointer
::nlohmann::json_pointer< basic_json > json_pointer
JSON Pointer.
Definition: json.hpp:202
nlohmann::basic_json::parse_event_t
typename parser::parse_event_t parse_event_t
parser event types
Definition: json.hpp:1055
nlohmann::basic_json::front
const_reference front() const
access the first element
Definition: json.hpp:3386
nlohmann::basic_json::max_size
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4438
nlohmann::basic_json::operator[]
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3054
nlohmann::detail::parser::parse
void parse(const bool strict, BasicJsonType &result)
public parser interface
Definition: parser.hpp:75
nlohmann::basic_json::get_ptr
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2596
nlohmann::detail::internal_iterator
an iterator value
Definition: internal_iterator.hpp:15
nlohmann::basic_json::operator+=
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4639
nlohmann::basic_json::back
const_reference back() const
access the last element
Definition: json.hpp:3432
nlohmann::basic_json::at
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition: json.hpp:6801
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:3255
nlohmann::basic_json::iterator_wrapper
static JSON_DEPRECATED iteration_proxy< const_iterator > iterator_wrapper(const_reference ref) noexcept
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4175
nlohmann::basic_json::push_back
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4665
nlohmann::basic_json::is_array
constexpr bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2183
nlohmann::json_pointer::array_index
static int array_index(const std::string &s)
Definition: json_pointer.hpp:85
nlohmann::basic_json::end
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:3939
nlohmann::basic_json::operator<<
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5796
nlohmann::basic_json::cbegin
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:3898
nlohmann::basic_json::rbegin
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:3999
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:260
nlohmann::basic_json::from_ubjson
static basic_json from_ubjson(detail::input_adapter i, const bool strict=true)
create a JSON value from an input in UBJSON format
Definition: json.hpp:6675
nlohmann::basic_json::pointer
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:258
nlohmann::basic_json::number_integer_t
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:665
nlohmann::basic_json::operator>=
friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5751
nlohmann::detail::iteration_proxy
proxy class for the items() function
Definition: iter_impl.hpp:19
nlohmann::basic_json::operator!=
friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
comparison: not equal
Definition: json.hpp:5486
nlohmann::basic_json::swap
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5308
nlohmann::basic_json::patch
basic_json patch(const basic_json &json_patch) const
applies a JSON patch
Definition: json.hpp:6969
nlohmann::basic_json::parser_callback_t
typename parser::parser_callback_t parser_callback_t
per-element parser callback type
Definition: json.hpp:1106
nlohmann::basic_json::type
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:1923
nlohmann::basic_json::operator+=
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4605
nlohmann::basic_json::operator<=
friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5648
nlohmann::basic_json::insert
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:4862
nlohmann::basic_json::items
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
Definition: json.hpp:4232
nlohmann::detail::output_adapter
Definition: output_adapters.hpp:92
nlohmann::basic_json::merge_patch
void merge_patch(const basic_json &patch)
applies a JSON Merge Patch
Definition: json.hpp:7443
nlohmann::basic_json::operator[]
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3193
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:3325
nlohmann::basic_json::insert
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:4965
nlohmann::basic_json::basic_json
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition: json.hpp:1171
nlohmann::basic_json::get_ref
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:2686
nlohmann::basic_json::operator<
friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5613
nlohmann::basic_json::from_cbor
static basic_json from_cbor(detail::input_adapter i, const bool strict=true)
create a JSON value from an input in CBOR format
Definition: json.hpp:6517
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:7504