to_json.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. // __ _____ _____ _____
  2. // __| | __| | | | JSON for Modern C++
  3. // | | |__ | | | | | | version 3.11.3
  4. // |_____|_____|_____|_|___| https://github.com/nlohmann/json
  5. //
  6. // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  7. // SPDX-License-Identifier: MIT
  8. #pragma once
  9. #include <algorithm> // copy
  10. #include <iterator> // begin, end
  11. #include <string> // string
  12. #include <tuple> // tuple, get
  13. #include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
  14. #include <utility> // move, forward, declval, pair
  15. #include <valarray> // valarray
  16. #include <vector> // vector
  17. #include <nlohmann/detail/iterators/iteration_proxy.hpp>
  18. #include <nlohmann/detail/macro_scope.hpp>
  19. #include <nlohmann/detail/meta/cpp_future.hpp>
  20. #include <nlohmann/detail/meta/std_fs.hpp>
  21. #include <nlohmann/detail/meta/type_traits.hpp>
  22. #include <nlohmann/detail/value_t.hpp>
  23. NLOHMANN_JSON_NAMESPACE_BEGIN
  24. namespace detail
  25. {
  26. //////////////////
  27. // constructors //
  28. //////////////////
  29. /*
  30. * Note all external_constructor<>::construct functions need to call
  31. * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
  32. * allocated value (e.g., a string). See bug issue
  33. * https://github.com/nlohmann/json/issues/2865 for more information.
  34. */
  35. template<value_t> struct external_constructor;
  36. template<>
  37. struct external_constructor<value_t::boolean>
  38. {
  39. template<typename BasicJsonType>
  40. static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
  41. {
  42. j.m_data.m_value.destroy(j.m_data.m_type);
  43. j.m_data.m_type = value_t::boolean;
  44. j.m_data.m_value = b;
  45. j.assert_invariant();
  46. }
  47. };
  48. template<>
  49. struct external_constructor<value_t::string>
  50. {
  51. template<typename BasicJsonType>
  52. static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
  53. {
  54. j.m_data.m_value.destroy(j.m_data.m_type);
  55. j.m_data.m_type = value_t::string;
  56. j.m_data.m_value = s;
  57. j.assert_invariant();
  58. }
  59. template<typename BasicJsonType>
  60. static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
  61. {
  62. j.m_data.m_value.destroy(j.m_data.m_type);
  63. j.m_data.m_type = value_t::string;
  64. j.m_data.m_value = std::move(s);
  65. j.assert_invariant();
  66. }
  67. template < typename BasicJsonType, typename CompatibleStringType,
  68. enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
  69. int > = 0 >
  70. static void construct(BasicJsonType& j, const CompatibleStringType& str)
  71. {
  72. j.m_data.m_value.destroy(j.m_data.m_type);
  73. j.m_data.m_type = value_t::string;
  74. j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
  75. j.assert_invariant();
  76. }
  77. };
  78. template<>
  79. struct external_constructor<value_t::binary>
  80. {
  81. template<typename BasicJsonType>
  82. static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
  83. {
  84. j.m_data.m_value.destroy(j.m_data.m_type);
  85. j.m_data.m_type = value_t::binary;
  86. j.m_data.m_value = typename BasicJsonType::binary_t(b);
  87. j.assert_invariant();
  88. }
  89. template<typename BasicJsonType>
  90. static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
  91. {
  92. j.m_data.m_value.destroy(j.m_data.m_type);
  93. j.m_data.m_type = value_t::binary;
  94. j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
  95. j.assert_invariant();
  96. }
  97. };
  98. template<>
  99. struct external_constructor<value_t::number_float>
  100. {
  101. template<typename BasicJsonType>
  102. static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
  103. {
  104. j.m_data.m_value.destroy(j.m_data.m_type);
  105. j.m_data.m_type = value_t::number_float;
  106. j.m_data.m_value = val;
  107. j.assert_invariant();
  108. }
  109. };
  110. template<>
  111. struct external_constructor<value_t::number_unsigned>
  112. {
  113. template<typename BasicJsonType>
  114. static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
  115. {
  116. j.m_data.m_value.destroy(j.m_data.m_type);
  117. j.m_data.m_type = value_t::number_unsigned;
  118. j.m_data.m_value = val;
  119. j.assert_invariant();
  120. }
  121. };
  122. template<>
  123. struct external_constructor<value_t::number_integer>
  124. {
  125. template<typename BasicJsonType>
  126. static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
  127. {
  128. j.m_data.m_value.destroy(j.m_data.m_type);
  129. j.m_data.m_type = value_t::number_integer;
  130. j.m_data.m_value = val;
  131. j.assert_invariant();
  132. }
  133. };
  134. template<>
  135. struct external_constructor<value_t::array>
  136. {
  137. template<typename BasicJsonType>
  138. static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
  139. {
  140. j.m_data.m_value.destroy(j.m_data.m_type);
  141. j.m_data.m_type = value_t::array;
  142. j.m_data.m_value = arr;
  143. j.set_parents();
  144. j.assert_invariant();
  145. }
  146. template<typename BasicJsonType>
  147. static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
  148. {
  149. j.m_data.m_value.destroy(j.m_data.m_type);
  150. j.m_data.m_type = value_t::array;
  151. j.m_data.m_value = std::move(arr);
  152. j.set_parents();
  153. j.assert_invariant();
  154. }
  155. template < typename BasicJsonType, typename CompatibleArrayType,
  156. enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
  157. int > = 0 >
  158. static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
  159. {
  160. using std::begin;
  161. using std::end;
  162. j.m_data.m_value.destroy(j.m_data.m_type);
  163. j.m_data.m_type = value_t::array;
  164. j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
  165. j.set_parents();
  166. j.assert_invariant();
  167. }
  168. template<typename BasicJsonType>
  169. static void construct(BasicJsonType& j, const std::vector<bool>& arr)
  170. {
  171. j.m_data.m_value.destroy(j.m_data.m_type);
  172. j.m_data.m_type = value_t::array;
  173. j.m_data.m_value = value_t::array;
  174. j.m_data.m_value.array->reserve(arr.size());
  175. for (const bool x : arr)
  176. {
  177. j.m_data.m_value.array->push_back(x);
  178. j.set_parent(j.m_data.m_value.array->back());
  179. }
  180. j.assert_invariant();
  181. }
  182. template<typename BasicJsonType, typename T,
  183. enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
  184. static void construct(BasicJsonType& j, const std::valarray<T>& arr)
  185. {
  186. j.m_data.m_value.destroy(j.m_data.m_type);
  187. j.m_data.m_type = value_t::array;
  188. j.m_data.m_value = value_t::array;
  189. j.m_data.m_value.array->resize(arr.size());
  190. if (arr.size() > 0)
  191. {
  192. std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
  193. }
  194. j.set_parents();
  195. j.assert_invariant();
  196. }
  197. };
  198. template<>
  199. struct external_constructor<value_t::object>
  200. {
  201. template<typename BasicJsonType>
  202. static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
  203. {
  204. j.m_data.m_value.destroy(j.m_data.m_type);
  205. j.m_data.m_type = value_t::object;
  206. j.m_data.m_value = obj;
  207. j.set_parents();
  208. j.assert_invariant();
  209. }
  210. template<typename BasicJsonType>
  211. static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
  212. {
  213. j.m_data.m_value.destroy(j.m_data.m_type);
  214. j.m_data.m_type = value_t::object;
  215. j.m_data.m_value = std::move(obj);
  216. j.set_parents();
  217. j.assert_invariant();
  218. }
  219. template < typename BasicJsonType, typename CompatibleObjectType,
  220. enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
  221. static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
  222. {
  223. using std::begin;
  224. using std::end;
  225. j.m_data.m_value.destroy(j.m_data.m_type);
  226. j.m_data.m_type = value_t::object;
  227. j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
  228. j.set_parents();
  229. j.assert_invariant();
  230. }
  231. };
  232. /////////////
  233. // to_json //
  234. /////////////
  235. template<typename BasicJsonType, typename T,
  236. enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
  237. inline void to_json(BasicJsonType& j, T b) noexcept
  238. {
  239. external_constructor<value_t::boolean>::construct(j, b);
  240. }
  241. template < typename BasicJsonType, typename BoolRef,
  242. enable_if_t <
  243. ((std::is_same<std::vector<bool>::reference, BoolRef>::value
  244. && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
  245. || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
  246. && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
  247. typename BasicJsonType::boolean_t >::value))
  248. && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
  249. inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
  250. {
  251. external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
  252. }
  253. template<typename BasicJsonType, typename CompatibleString,
  254. enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
  255. inline void to_json(BasicJsonType& j, const CompatibleString& s)
  256. {
  257. external_constructor<value_t::string>::construct(j, s);
  258. }
  259. template<typename BasicJsonType>
  260. inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
  261. {
  262. external_constructor<value_t::string>::construct(j, std::move(s));
  263. }
  264. template<typename BasicJsonType, typename FloatType,
  265. enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
  266. inline void to_json(BasicJsonType& j, FloatType val) noexcept
  267. {
  268. external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
  269. }
  270. template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
  271. enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
  272. inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
  273. {
  274. external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
  275. }
  276. template<typename BasicJsonType, typename CompatibleNumberIntegerType,
  277. enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
  278. inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
  279. {
  280. external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
  281. }
  282. #if !JSON_DISABLE_ENUM_SERIALIZATION
  283. template<typename BasicJsonType, typename EnumType,
  284. enable_if_t<std::is_enum<EnumType>::value, int> = 0>
  285. inline void to_json(BasicJsonType& j, EnumType e) noexcept
  286. {
  287. using underlying_type = typename std::underlying_type<EnumType>::type;
  288. external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
  289. }
  290. #endif // JSON_DISABLE_ENUM_SERIALIZATION
  291. template<typename BasicJsonType>
  292. inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
  293. {
  294. external_constructor<value_t::array>::construct(j, e);
  295. }
  296. template < typename BasicJsonType, typename CompatibleArrayType,
  297. enable_if_t < is_compatible_array_type<BasicJsonType,
  298. CompatibleArrayType>::value&&
  299. !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
  300. !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
  301. !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
  302. !is_basic_json<CompatibleArrayType>::value,
  303. int > = 0 >
  304. inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
  305. {
  306. external_constructor<value_t::array>::construct(j, arr);
  307. }
  308. template<typename BasicJsonType>
  309. inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
  310. {
  311. external_constructor<value_t::binary>::construct(j, bin);
  312. }
  313. template<typename BasicJsonType, typename T,
  314. enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
  315. inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
  316. {
  317. external_constructor<value_t::array>::construct(j, std::move(arr));
  318. }
  319. template<typename BasicJsonType>
  320. inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
  321. {
  322. external_constructor<value_t::array>::construct(j, std::move(arr));
  323. }
  324. template < typename BasicJsonType, typename CompatibleObjectType,
  325. enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
  326. inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
  327. {
  328. external_constructor<value_t::object>::construct(j, obj);
  329. }
  330. template<typename BasicJsonType>
  331. inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
  332. {
  333. external_constructor<value_t::object>::construct(j, std::move(obj));
  334. }
  335. template <
  336. typename BasicJsonType, typename T, std::size_t N,
  337. enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
  338. const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
  339. int > = 0 >
  340. inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
  341. {
  342. external_constructor<value_t::array>::construct(j, arr);
  343. }
  344. template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
  345. inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
  346. {
  347. j = { p.first, p.second };
  348. }
  349. // for https://github.com/nlohmann/json/pull/1134
  350. template<typename BasicJsonType, typename T,
  351. enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
  352. inline void to_json(BasicJsonType& j, const T& b)
  353. {
  354. j = { {b.key(), b.value()} };
  355. }
  356. template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
  357. inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
  358. {
  359. j = { std::get<Idx>(t)... };
  360. }
  361. template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
  362. inline void to_json(BasicJsonType& j, const T& t)
  363. {
  364. to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
  365. }
  366. #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
  367. template<typename BasicJsonType>
  368. inline void to_json(BasicJsonType& j, const std_fs::path& p)
  369. {
  370. j = p.string();
  371. }
  372. #endif
  373. struct to_json_fn
  374. {
  375. template<typename BasicJsonType, typename T>
  376. auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
  377. -> decltype(to_json(j, std::forward<T>(val)), void())
  378. {
  379. return to_json(j, std::forward<T>(val));
  380. }
  381. };
  382. } // namespace detail
  383. #ifndef JSON_HAS_CPP_17
  384. /// namespace to hold default `to_json` function
  385. /// to see why this is required:
  386. /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
  387. namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
  388. {
  389. #endif
  390. JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
  391. detail::static_const<detail::to_json_fn>::value;
  392. #ifndef JSON_HAS_CPP_17
  393. } // namespace
  394. #endif
  395. NLOHMANN_JSON_NAMESPACE_END