libfly  6.2.2
C++20 utility library for Linux, macOS, and Windows
json.hpp
1 #pragma once
2 
3 #include "fly/concepts/concepts.hpp"
4 #include "fly/types/json/concepts.hpp"
5 #include "fly/types/json/detail/array_util.hpp"
6 #include "fly/types/json/detail/json_iterator.hpp"
7 #include "fly/types/json/detail/json_reverse_iterator.hpp"
8 #include "fly/types/json/json_exception.hpp"
9 #include "fly/types/json/types.hpp"
10 #include "fly/types/numeric/literals.hpp"
11 #include "fly/types/string/concepts.hpp"
12 #include "fly/types/string/string.hpp"
13 
14 #include <concepts>
15 #include <cstddef>
16 #include <cstdint>
17 #include <exception>
18 #include <functional>
19 #include <initializer_list>
20 #include <map>
21 #include <optional>
22 #include <string>
23 #include <type_traits>
24 #include <variant>
25 #include <vector>
26 
27 // Helper macros to choose the correct string literal prefix to use for JSON string types.
28 #define FLY_JSON_CHR(ch) FLY_CHR(fly::json_char_type, ch)
29 #define FLY_JSON_STR(str) FLY_STR(fly::json_char_type, str)
30 #define FLY_JSON_ARR(arr) FLY_ARR(fly::json_char_type, arr)
31 
32 namespace fly {
33 
161 class Json
162 {
163 public:
167  using value_type = Json;
168  using size_type = std::size_t;
169  using difference_type = std::ptrdiff_t;
170  using allocator_type = std::allocator<value_type>;
171  using reference = value_type &;
172  using const_reference = const value_type &;
173  using pointer = typename std::allocator_traits<allocator_type>::pointer;
174  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
179 
183  Json() = default;
184 
190  Json(json_null_type value) noexcept;
191 
203  template <JsonStringLike T>
204  Json(T value) noexcept(false);
205 
217  template <JsonObject T>
218  Json(T value) noexcept(false);
219 
230  template <JsonArray T>
231  Json(T value) noexcept(false);
232 
242  template <JsonBoolean T>
243  Json(T value) noexcept;
244 
254  template <JsonSignedInteger T>
255  Json(T value) noexcept;
256 
266  template <JsonUnsignedInteger T>
267  Json(T value) noexcept;
268 
278  template <JsonFloatingPoint T>
279  Json(T value) noexcept;
280 
287  Json(const_reference json) noexcept;
288 
295  Json(Json &&json) noexcept;
296 
305  Json(std::initializer_list<Json> initializer) noexcept;
306 
315  reference operator=(Json json) noexcept;
316 
322  json_string_type serialize() const;
323 
327  bool is_null() const;
328 
332  bool is_string() const;
333 
337  bool is_object() const;
338 
346  bool is_object_like() const;
347 
351  bool is_array() const;
352 
356  bool is_boolean() const;
357 
361  bool is_signed_integer() const;
362 
366  bool is_unsigned_integer() const;
367 
371  bool is_float() const;
372 
373  //==============================================================================================
374  //
375  // Conversion operators
376  //
377  //==============================================================================================
378 
386  explicit operator json_null_type() const noexcept(false);
387 
403  template <JsonString T>
404  explicit operator T() const &noexcept(false);
405 
414  explicit operator json_string_type() &&noexcept(false);
415 
427  template <JsonObject T>
428  explicit operator T() const &noexcept(false);
429 
438  explicit operator json_object_type() &&noexcept(false);
439 
452  template <JsonArray T>
453  explicit operator T() const &noexcept(false);
454 
463  explicit operator json_array_type() &&noexcept(false);
464 
478  template <typename T, std::size_t N>
479  explicit operator std::array<T, N>() const noexcept(false);
480 
491  template <JsonBoolean T>
492  explicit operator T() const noexcept;
493 
508  template <JsonNumber T>
509  explicit operator T() const noexcept(false);
510 
511  //==============================================================================================
512  //
513  // Element accessors
514  //
515  //==============================================================================================
516 
532  template <JsonStringLike T>
533  reference at(T key);
534 
550  template <JsonStringLike T>
551  const_reference at(T key) const;
552 
564  reference at(size_type index);
565 
577  const_reference at(size_type index) const;
578 
597  template <JsonStringLike T>
598  reference operator[](T key);
599 
613  template <JsonStringLike T>
614  const_reference operator[](T key) const;
615 
630  reference operator[](size_type index);
631 
643  const_reference operator[](size_type index) const;
644 
657  reference front();
658 
671  const_reference front() const;
672 
685  reference back();
686 
699  const_reference back() const;
700 
701  //==============================================================================================
702  //
703  // Iterators
704  //
705  //==============================================================================================
706 
714  iterator begin();
715 
723  const_iterator begin() const;
724 
732  const_iterator cbegin() const;
733 
741  iterator end();
742 
750  const_iterator end() const;
751 
759  const_iterator cend() const;
760 
769 
778 
787 
796 
805 
814 
815  //==============================================================================================
816  //
817  // Capacity
818  //
819  //==============================================================================================
820 
833  bool empty() const;
834 
849  size_type size() const;
850 
859  void resize(size_type size);
860 
876  size_type capacity() const;
877 
886  void reserve(size_type capacity);
887 
888  //==============================================================================================
889  //
890  // Modifiers
891  //
892  //==============================================================================================
893 
903  void clear();
904 
921  template <JsonStringLike Key>
922  std::pair<iterator, bool> insert(Key key, const Json &value);
923 
940  template <JsonStringLike Key>
941  std::pair<iterator, bool> insert(Key key, Json &&value);
942 
954  void insert(const_iterator first, const_iterator last);
955 
968  iterator insert(const_iterator position, const Json &value);
969 
982  iterator insert(const_iterator position, Json &&value);
983 
997  iterator insert(const_iterator position, size_type count, const Json &value);
998 
1017 
1030  iterator insert(const_iterator position, std::initializer_list<Json> initializer);
1031 
1048  template <JsonStringLike Key>
1049  std::pair<iterator, bool> insert_or_assign(Key key, Json &&value);
1050 
1069  template <JsonStringLike Key, typename Value>
1070  std::pair<iterator, bool> emplace(Key key, Value &&value);
1071 
1085  template <typename... Args>
1086  Json::reference emplace_back(Args &&...args);
1087 
1097  void push_back(const Json &value);
1098 
1107  void push_back(Json &&value);
1108 
1114  void pop_back();
1115 
1129  template <JsonStringLike T>
1130  size_type erase(T key);
1131 
1140  void erase(size_type index);
1141 
1157  iterator erase(const_iterator position);
1158 
1172 
1178  void swap(reference json);
1179 
1194  template <JsonString T>
1195  void swap(T &other);
1196 
1208  template <JsonObject T>
1209  void swap(T &other);
1210 
1222  template <JsonArray T>
1223  void swap(T &other);
1224 
1238  void merge(Json &other);
1239 
1253  void merge(Json &&other);
1254 
1268  template <JsonObject T>
1269  void merge(T &other);
1270 
1284  template <JsonObject T>
1285  void merge(T &&other);
1286 
1287  //==============================================================================================
1288  //
1289  // Lookup
1290  //
1291  //==============================================================================================
1292 
1306  template <JsonStringLike T>
1307  size_type count(T key) const;
1308 
1323  template <JsonStringLike T>
1324  iterator find(T key);
1325 
1340  template <JsonStringLike T>
1341  const_iterator find(T key) const;
1342 
1356  template <JsonStringLike T>
1357  bool contains(T key) const;
1358 
1359  //==============================================================================================
1360  //
1361  // Non-member functions
1362  //
1363  //==============================================================================================
1364 
1379  friend bool operator==(const_reference json1, const_reference json2);
1380 
1387  friend bool operator!=(const_reference json1, const_reference json2);
1388 
1407  friend bool operator<(const_reference json1, const_reference json2);
1408 
1415  friend bool operator<=(const_reference json1, const_reference json2);
1416 
1423  friend bool operator>(const_reference json1, const_reference json2);
1424 
1432  friend bool operator>=(const_reference json1, const_reference json2);
1433 
1434 private:
1435  friend iterator;
1436  friend const_iterator;
1437  friend struct std::hash<Json>;
1438 
1450  template <JsonStringLike T>
1451  static json_string_type convert_to_string(T value);
1452 
1463  static json_string_type validate_string(json_string_type &&value);
1464 
1476  static void read_escaped_character(json_string_type &value, json_string_type::iterator &it);
1477 
1486  static void write_escaped_character(
1487  json_string_type &output,
1488  json_string_type::const_iterator &it,
1489  const json_string_type::const_iterator &end);
1490 
1495  template <typename... Args>
1496  using object_insertion_result = std::conditional_t<
1497  std::is_void_v<decltype(std::declval<json_object_type>().insert(std::declval<Args>()...))>,
1498  void,
1499  std::pair<iterator, bool>>;
1500 
1516  template <typename... Args>
1517  object_insertion_result<Args...> object_inserter(Args &&...args);
1518 
1533  template <typename... Args>
1534  iterator array_inserter(const_iterator position, Args &&...args);
1535 
1548  template <typename T>
1549  T &get(const char *error_message);
1550 
1564  template <typename T>
1565  T &get_or_promote(const char *error_message);
1566 
1579  template <typename T>
1580  const T &get(const char *error_message) const;
1581 
1582  json_type m_value {nullptr};
1583 };
1584 
1585 //==================================================================================================
1586 template <JsonStringLike T>
1587 Json::Json(T value) noexcept(false) : m_value(convert_to_string(std::move(value)))
1588 {
1589 }
1590 
1591 //==================================================================================================
1592 template <JsonObject T>
1593 Json::Json(T value) noexcept(false) : m_value(json_object_type())
1594 {
1595  for (auto &it : value)
1596  {
1597  insert(std::move(it.first), std::move(it.second));
1598  }
1599 }
1600 
1601 //==================================================================================================
1602 template <JsonArray T>
1603 Json::Json(T value) noexcept(false) : m_value(json_array_type())
1604 {
1605  reserve(detail::json_array_size(value));
1606 
1607  for (auto &it : value)
1608  {
1609  push_back(std::move(it));
1610  }
1611 }
1612 
1613 //==================================================================================================
1614 template <JsonBoolean T>
1615 Json::Json(T value) noexcept : m_value(static_cast<json_boolean_type>(value))
1616 {
1617 }
1618 
1619 //==================================================================================================
1620 template <JsonSignedInteger T>
1621 Json::Json(T value) noexcept : m_value(static_cast<json_signed_integer_type>(value))
1622 {
1623 }
1624 
1625 //==================================================================================================
1626 template <JsonUnsignedInteger T>
1627 Json::Json(T value) noexcept : m_value(static_cast<json_unsigned_integer_type>(value))
1628 {
1629 }
1630 
1631 //==================================================================================================
1632 template <JsonFloatingPoint T>
1633 Json::Json(T value) noexcept : m_value(static_cast<json_floating_point_type>(value))
1634 {
1635 }
1636 
1637 //==================================================================================================
1638 template <JsonString T>
1639 Json::operator T() const &noexcept(false)
1640 {
1641  auto visitor = [this](const auto &storage) -> T {
1642  using S = decltype(storage);
1643 
1644  if constexpr (JsonString<S>)
1645  {
1646  if constexpr (fly::SameAs<T, json_string_type>)
1647  {
1648  return storage;
1649  }
1650  else
1651  {
1652  // The JSON string will have been validated for Unicode compliance during
1653  // construction.
1654  return *(JsonStringType::convert<T>(storage));
1655  }
1656  }
1657  else if constexpr (JsonNumber<S>)
1658  {
1659  using char_type = typename T::value_type;
1660  return BasicString<char_type>::format(FLY_ARR(char_type, "{}"), storage);
1661  }
1662  else
1663  {
1664  throw JsonException(*this, "JSON type is not a string");
1665  }
1666  };
1667 
1668  return std::visit(std::move(visitor), m_value);
1669 }
1670 
1671 //==================================================================================================
1672 template <JsonObject T>
1673 Json::operator T() const &noexcept(false)
1674 {
1675  const auto &storage = get<json_object_type>("JSON type is not an object");
1676  T result;
1677 
1678  for (const auto &it : storage)
1679  {
1680  // The JSON string will have been validated for Unicode compliance during construction.
1681  auto key = *std::move(JsonStringType::convert<typename T::key_type>(it.first));
1682  result.emplace(std::move(key), it.second);
1683  }
1684 
1685  return result;
1686 }
1687 
1688 //==================================================================================================
1689 template <JsonArray T>
1690 Json::operator T() const &noexcept(false)
1691 {
1692  const auto &storage = get<json_array_type>("JSON type is not an array");
1693  T result {};
1694 
1695  for (const auto &it : storage)
1696  {
1697  auto copy = static_cast<typename T::value_type>(it);
1698  detail::json_array_append(result, std::move(copy));
1699  }
1700 
1701  return result;
1702 }
1703 
1704 //==================================================================================================
1705 template <typename T, std::size_t N>
1706 Json::operator std::array<T, N>() const noexcept(false)
1707 {
1708  const auto &storage = get<json_array_type>("JSON type is not an array");
1709  std::array<T, N> result {};
1710 
1711  for (std::size_t i = 0; i < std::min(N, storage.size()); ++i)
1712  {
1713  result[i] = T(storage.at(i));
1714  }
1715 
1716  return result;
1717 }
1718 
1719 //==================================================================================================
1720 template <JsonBoolean T>
1721 Json::operator T() const noexcept
1722 {
1723  auto visitor = [](const auto &storage) noexcept -> T {
1724  using S = decltype(storage);
1725 
1726  if constexpr (JsonContainer<S>)
1727  {
1728  return !storage.empty();
1729  }
1730  else if constexpr (JsonFloatingPoint<S>)
1731  {
1732  return std::abs(storage) > static_cast<S>(0);
1733  }
1734  else if constexpr (JsonNull<S>)
1735  {
1736  return false;
1737  }
1738  else
1739  {
1740  return storage != static_cast<S>(0);
1741  }
1742  };
1743 
1744  return std::visit(std::move(visitor), m_value);
1745 }
1746 
1747 //==================================================================================================
1748 template <JsonNumber T>
1749 Json::operator T() const noexcept(false)
1750 {
1751  auto visitor = [this](const auto &storage) -> T {
1752  using S = decltype(storage);
1753 
1754  if constexpr (JsonString<S>)
1755  {
1756  if (auto converted = JsonStringType::convert<T>(storage); converted)
1757  {
1758  return *std::move(converted);
1759  }
1760  }
1761  else if constexpr (JsonNumber<S>)
1762  {
1763  return static_cast<T>(storage);
1764  }
1765 
1766  throw JsonException(*this, "JSON type is not numeric");
1767  };
1768 
1769  return std::visit(std::move(visitor), m_value);
1770 }
1771 
1772 //==================================================================================================
1773 template <JsonStringLike T>
1775 {
1776  auto &storage = get<json_object_type>("JSON type invalid for operator[key]");
1777  auto it = storage.find(convert_to_string(std::move(key)));
1778 
1779  if (it == storage.end())
1780  {
1781  throw JsonException(*this, String::format("Given key ({}) not found", key));
1782  }
1783 
1784  return it->second;
1785 }
1786 
1787 //==================================================================================================
1788 template <JsonStringLike T>
1790 {
1791  const auto &storage = get<json_object_type>("JSON type invalid for operator[key]");
1792  const auto it = storage.find(convert_to_string(std::move(key)));
1793 
1794  if (it == storage.end())
1795  {
1796  throw JsonException(*this, String::format("Given key ({}) not found", key));
1797  }
1798 
1799  return it->second;
1800 }
1801 
1802 //==================================================================================================
1803 template <JsonStringLike T>
1805 {
1806  auto &storage = get_or_promote<json_object_type>("JSON type invalid for operator[key]");
1807  return storage[convert_to_string(std::move(key))];
1808 }
1809 
1810 //==================================================================================================
1811 template <JsonStringLike T>
1813 {
1814  return at(key);
1815 }
1816 
1817 //==================================================================================================
1818 template <JsonStringLike Key>
1819 std::pair<Json::iterator, bool> Json::insert(Key key, const Json &value)
1820 {
1821  return object_inserter(std::make_pair(convert_to_string(std::move(key)), value));
1822 }
1823 
1824 //==================================================================================================
1825 template <JsonStringLike Key>
1826 std::pair<Json::iterator, bool> Json::insert(Key key, Json &&value)
1827 {
1828  return object_inserter(std::make_pair(convert_to_string(std::move(key)), std::move(value)));
1829 }
1830 
1831 //==================================================================================================
1832 template <JsonStringLike Key>
1833 std::pair<Json::iterator, bool> Json::insert_or_assign(Key key, Json &&value)
1834 {
1835  auto result = insert(key, value);
1836 
1837  if (!result.second)
1838  {
1839  auto &it = std::get<typename iterator::object_iterator_type>(result.first.m_iterator);
1840  it->second.swap(value);
1841  }
1842 
1843  return result;
1844 }
1845 
1846 //==================================================================================================
1847 template <JsonStringLike Key, typename Value>
1848 std::pair<Json::iterator, bool> Json::emplace(Key key, Value &&value)
1849 {
1850  auto &storage = get_or_promote<json_object_type>("JSON type invalid for object emplacement");
1851  auto result = storage.emplace(convert_to_string(std::move(key)), std::forward<Value>(value));
1852 
1853  auto it = end();
1854  it.m_iterator = result.first;
1855 
1856  return {it, result.second};
1857 }
1858 
1859 //==================================================================================================
1860 template <typename... Args>
1862 {
1863  auto &storage = get_or_promote<json_array_type>("JSON type invalid for array emplacement");
1864  return storage.emplace_back(std::forward<Args>(args)...);
1865 }
1866 
1867 //==================================================================================================
1868 template <JsonStringLike T>
1869 Json::size_type Json::erase(T key)
1870 {
1871  auto &storage = get<json_object_type>("JSON type invalid for erase(key)");
1872  return storage.erase(convert_to_string(std::move(key)));
1873 }
1874 
1875 //==================================================================================================
1876 template <JsonString T>
1877 void Json::swap(T &other)
1878 {
1879  if (!is_string())
1880  {
1881  throw JsonException(*this, "JSON type invalid for swap(string)");
1882  }
1883 
1884  T string = static_cast<T>(*this);
1885 
1886  *this = std::move(other);
1887  other = std::move(string);
1888 }
1889 
1890 //==================================================================================================
1891 template <JsonObject T>
1892 void Json::swap(T &other)
1893 {
1894  if (!is_object())
1895  {
1896  throw JsonException(*this, "JSON type invalid for swap(object)");
1897  }
1898 
1899  T object = static_cast<T>(*this);
1900 
1901  *this = std::move(other);
1902  other = std::move(object);
1903 }
1904 
1905 //==================================================================================================
1906 template <JsonArray T>
1907 void Json::swap(T &other)
1908 {
1909  if (!is_array())
1910  {
1911  throw JsonException(*this, "JSON type invalid for swap(array)");
1912  }
1913 
1914  T array = static_cast<T>(*this);
1915 
1916  *this = std::move(other);
1917  other = std::move(array);
1918 }
1919 
1920 //==================================================================================================
1921 template <JsonObject T>
1922 void Json::merge(T &other)
1923 {
1924  get_or_promote<json_object_type>("JSON type invalid for merging");
1925 
1926  // Manual implementation of fly::json_object_type::merge(&) to allow unordered maps.
1927  for (auto it = other.begin(); it != other.end();)
1928  {
1929  if (contains(it->first))
1930  {
1931  ++it;
1932  }
1933  else
1934  {
1935  insert(std::move(it->first), std::move(it->second));
1936  it = other.erase(it);
1937  }
1938  }
1939 }
1940 
1941 //==================================================================================================
1942 template <JsonObject T>
1943 void Json::merge(T &&other)
1944 {
1945  get_or_promote<json_object_type>("JSON type invalid for merging");
1946 
1947  // Manual implementation of fly::json_object_type::merge(&&) to allow unordered maps.
1948  for (auto &&it : other)
1949  {
1950  if (!contains(it.first))
1951  {
1952  insert(std::move(it.first), std::move(it.second));
1953  }
1954  }
1955 }
1956 
1957 //==================================================================================================
1958 template <JsonStringLike T>
1959 Json::size_type Json::count(T key) const
1960 {
1961  const auto &storage = get<json_object_type>("JSON type invalid for count(key)");
1962  return storage.count(convert_to_string(std::move(key)));
1963 }
1964 
1965 //==================================================================================================
1966 template <JsonStringLike T>
1968 {
1969  auto &storage = get<json_object_type>("JSON type invalid for find(key)");
1970 
1971  auto it = end();
1972  it.m_iterator = storage.find(convert_to_string(std::move(key)));
1973 
1974  return it;
1975 }
1976 
1977 //==================================================================================================
1978 template <JsonStringLike T>
1980 {
1981  const auto &storage = get<json_object_type>("JSON type invalid for find(key)");
1982 
1983  auto it = cend();
1984  it.m_iterator = storage.find(convert_to_string(std::move(key)));
1985 
1986  return it;
1987 }
1988 
1989 //==================================================================================================
1990 template <JsonStringLike T>
1991 bool Json::contains(T key) const
1992 {
1993  const auto &storage = get<json_object_type>("JSON type invalid for contains(key)");
1994  return storage.contains(convert_to_string(std::move(key)));
1995 }
1996 
1997 //==================================================================================================
1998 template <JsonStringLike T>
1999 json_string_type Json::convert_to_string(T value)
2000 {
2001  using StringType = BasicString<fly::StandardCharacterType<T>>;
2002 
2003  if constexpr (fly::SameAs<typename StringType::string_type, json_string_type>)
2004  {
2005  if (StringType::validate(value))
2006  {
2007  return validate_string(std::move(value));
2008  }
2009  }
2010  else
2011  {
2012  if (auto result = StringType::template convert<json_string_type>(value); result)
2013  {
2014  return validate_string(*std::move(result));
2015  }
2016  }
2017 
2018  throw JsonException("Could not convert string-like type to a JSON string");
2019 }
2020 
2021 //==================================================================================================
2022 template <typename... Args>
2023 Json::object_insertion_result<Args...> Json::object_inserter(Args &&...args)
2024 {
2025  auto &storage = get<json_object_type>("JSON type invalid for object insertion");
2026 
2027  if constexpr (std::is_void_v<object_insertion_result<Args...>>)
2028  {
2029  storage.insert(std::forward<Args>(args)...);
2030  }
2031  else
2032  {
2033  auto result = storage.insert(std::forward<Args>(args)...);
2034 
2035  auto it = end();
2036  it.m_iterator = result.first;
2037 
2038  return {it, result.second};
2039  }
2040 }
2041 
2042 //==================================================================================================
2043 template <typename... Args>
2044 Json::iterator Json::array_inserter(const_iterator position, Args &&...args)
2045 {
2046  auto &storage = get<json_array_type>("JSON type invalid for array insertion");
2047 
2048  if (position.m_json != this)
2049  {
2050  throw JsonException("Provided iterator is for a different Json instance");
2051  }
2052 
2053  const auto &position_iterator =
2054  std::get<typename const_iterator::array_iterator_type>(position.m_iterator);
2055 
2056  auto it = end();
2057  it.m_iterator = storage.insert(position_iterator, std::forward<Args>(args)...);
2058 
2059  return it;
2060 }
2061 
2062 //==================================================================================================
2063 template <typename T>
2064 inline T &Json::get(const char *error_message)
2065 {
2066  auto *storage = std::get_if<T>(&m_value);
2067 
2068  if (storage == nullptr)
2069  {
2070  throw JsonException(*this, error_message);
2071  }
2072 
2073  return *storage;
2074 }
2075 
2076 //==================================================================================================
2077 template <typename T>
2078 inline T &Json::get_or_promote(const char *error_message)
2079 {
2080  auto *storage = std::get_if<T>(&m_value);
2081 
2082  if (storage == nullptr)
2083  {
2084  if (is_null())
2085  {
2086  return m_value.emplace<T>();
2087  }
2088 
2089  throw JsonException(*this, error_message);
2090  }
2091 
2092  return *storage;
2093 }
2094 
2095 //==================================================================================================
2096 template <typename T>
2097 inline const T &Json::get(const char *error_message) const
2098 {
2099  const auto *storage = std::get_if<T>(&m_value);
2100 
2101  if (storage == nullptr)
2102  {
2103  throw JsonException(*this, error_message);
2104  }
2105 
2106  return *storage;
2107 }
2108 
2109 } // namespace fly
2110 
2111 //==================================================================================================
2112 template <typename CharType>
2113 struct fly::Formatter<fly::Json, CharType> :
2114  public fly::Formatter<std::basic_string<CharType>, CharType>
2115 {
2116  using string_type = std::basic_string<CharType>;
2117 
2126  template <typename FormatContext>
2127  void format(const fly::Json &json, FormatContext &context)
2128  {
2129  if constexpr (fly::SameAs<CharType, fly::json_char_type>)
2130  {
2132  }
2133  else
2134  {
2135  auto serialized = JsonStringType::convert<string_type>(json.serialize());
2136 
2137  // The JSON string will have been validated for Unicode compliance during construction.
2138  fly::Formatter<string_type, CharType>::format(*serialized, context);
2139  }
2140  }
2141 };
2142 
2143 //==================================================================================================
2144 template <>
2145 struct std::hash<fly::Json>
2146 {
2154  std::size_t operator()(const fly::Json &json) const
2155  {
2156  std::size_t type = json.m_value.index();
2157 
2158  auto visitor = [type](const auto &storage) -> std::size_t {
2159  using S = decltype(storage);
2160 
2161  if constexpr (fly::JsonNull<S>)
2162  {
2163  return hash_combine(type, 0);
2164  }
2165  else if constexpr (fly::JsonObject<S>)
2166  {
2167  std::hash<typename fly::json_object_type::key_type> key_hasher {};
2168  std::hash<typename fly::json_object_type::mapped_type> value_hasher {};
2169  std::size_t result = hash_combine(type, storage.size());
2170 
2171  for (const auto &value : storage)
2172  {
2173  result = hash_combine(result, key_hasher(value.first));
2174  result = hash_combine(result, value_hasher(value.second));
2175  }
2176 
2177  return result;
2178  }
2179  else if constexpr (fly::JsonArray<S>)
2180  {
2181  std::hash<typename fly::json_array_type::value_type> hasher {};
2182  std::size_t result = hash_combine(type, storage.size());
2183 
2184  for (const auto &value : storage)
2185  {
2186  result = hash_combine(result, hasher(value));
2187  }
2188 
2189  return result;
2190  }
2191  else
2192  {
2193  std::hash<std::remove_cvref_t<S>> hasher {};
2194  return hash_combine(type, hasher(storage));
2195  }
2196  };
2197 
2198  return std::visit(std::move(visitor), json.m_value);
2199  }
2200 
2201 private:
2210  static constexpr std::size_t hash_combine(std::size_t value1, std::size_t value2)
2211  {
2212  using namespace fly::literals::numeric_literals;
2213 
2214  value1 ^= value2 + 0x9e3779b9_zu + (value1 << 6_zu) + (value1 >> 2_zu);
2215  return value1;
2216  }
2217 };
Definition: string.hpp:51
static string_type format(FormatString< ParameterTypes... > &&fmt, ParameterTypes &&...parameters)
Definition: json_exception.hpp:19
Definition: json.hpp:162
Json(T value) noexcept
void pop_back()
Definition: json.cpp:612
size_type erase(T key)
Definition: json.hpp:1869
Json()=default
bool empty() const
Definition: json.cpp:388
const_iterator cbegin() const
Definition: json.cpp:328
reference front()
Definition: json.cpp:274
reference operator=(Json json) noexcept
Definition: json.cpp:57
const_reverse_iterator crend() const
Definition: json.cpp:382
bool is_signed_integer() const
Definition: json.cpp:178
size_type capacity() const
Definition: json.cpp:453
iterator end()
Definition: json.cpp:334
bool is_string() const
Definition: json.cpp:146
std::pair< iterator, bool > insert_or_assign(Key key, Json &&value)
Definition: json.hpp:1833
const_reverse_iterator crbegin() const
Definition: json.cpp:364
bool is_null() const
Definition: json.cpp:140
bool is_boolean() const
Definition: json.cpp:172
bool is_float() const
Definition: json.cpp:190
void clear()
Definition: json.cpp:507
iterator find(T key)
Definition: json.hpp:1967
bool contains(T key) const
Definition: json.hpp:1991
bool is_unsigned_integer() const
Definition: json.cpp:184
iterator begin()
Definition: json.cpp:316
bool is_object_like() const
Definition: json.cpp:158
reference back()
Definition: json.cpp:286
const_iterator cend() const
Definition: json.cpp:346
json_string_type serialize() const
Definition: json.cpp:64
bool is_object() const
Definition: json.cpp:152
reference at(T key)
Definition: json.hpp:1774
std::pair< iterator, bool > insert(Key key, const Json &value)
Definition: json.hpp:1819
void merge(Json &other)
Definition: json.cpp:710
void reserve(size_type capacity)
Definition: json.cpp:480
reference operator[](T key)
Definition: json.hpp:1804
reverse_iterator rend()
Definition: json.cpp:370
void resize(size_type size)
Definition: json.cpp:434
Json(T value) noexcept(false)
reverse_iterator rbegin()
Definition: json.cpp:352
size_type count(T key) const
Definition: json.hpp:1959
void push_back(const Json &value)
Definition: json.cpp:598
std::pair< iterator, bool > emplace(Key key, Value &&value)
Definition: json.hpp:1848
Json::reference emplace_back(Args &&...args)
Definition: json.hpp:1861
size_type size() const
Definition: json.cpp:411
bool is_array() const
Definition: json.cpp:166
void swap(reference json)
Definition: json.cpp:704
Definition: json_iterator.hpp:58
Definition: json_reverse_iterator.hpp:22
void format(const fly::Json &json, FormatContext &context)
Definition: json.hpp:2127
Definition: formatters.hpp:42
std::size_t operator()(const fly::Json &json) const
Definition: json.hpp:2154