to_json.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. #pragma once
  2. #include <ciso646> // or, and, not
  3. #include <iterator> // begin, end
  4. #include <tuple> // tuple, get
  5. #include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
  6. #include <utility> // move, forward, declval, pair
  7. #include <valarray> // valarray
  8. #include <vector> // vector
  9. #include <nlohmann/detail/meta.hpp>
  10. #include <nlohmann/detail/value_t.hpp>
  11. #include <nlohmann/detail/iterators/iteration_proxy.hpp>
  12. namespace nlohmann
  13. {
  14. namespace detail
  15. {
  16. //////////////////
  17. // constructors //
  18. //////////////////
  19. template<value_t> struct external_constructor;
  20. template<>
  21. struct external_constructor<value_t::boolean>
  22. {
  23. template<typename BasicJsonType>
  24. static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
  25. {
  26. j.m_type = value_t::boolean;
  27. j.m_value = b;
  28. j.assert_invariant();
  29. }
  30. };
  31. template<>
  32. struct external_constructor<value_t::string>
  33. {
  34. template<typename BasicJsonType>
  35. static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
  36. {
  37. j.m_type = value_t::string;
  38. j.m_value = s;
  39. j.assert_invariant();
  40. }
  41. template<typename BasicJsonType>
  42. static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
  43. {
  44. j.m_type = value_t::string;
  45. j.m_value = std::move(s);
  46. j.assert_invariant();
  47. }
  48. template<typename BasicJsonType, typename CompatibleStringType,
  49. enable_if_t<not std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
  50. int> = 0>
  51. static void construct(BasicJsonType& j, const CompatibleStringType& str)
  52. {
  53. j.m_type = value_t::string;
  54. j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
  55. j.assert_invariant();
  56. }
  57. };
  58. template<>
  59. struct external_constructor<value_t::number_float>
  60. {
  61. template<typename BasicJsonType>
  62. static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
  63. {
  64. j.m_type = value_t::number_float;
  65. j.m_value = val;
  66. j.assert_invariant();
  67. }
  68. };
  69. template<>
  70. struct external_constructor<value_t::number_unsigned>
  71. {
  72. template<typename BasicJsonType>
  73. static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
  74. {
  75. j.m_type = value_t::number_unsigned;
  76. j.m_value = val;
  77. j.assert_invariant();
  78. }
  79. };
  80. template<>
  81. struct external_constructor<value_t::number_integer>
  82. {
  83. template<typename BasicJsonType>
  84. static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
  85. {
  86. j.m_type = value_t::number_integer;
  87. j.m_value = val;
  88. j.assert_invariant();
  89. }
  90. };
  91. template<>
  92. struct external_constructor<value_t::array>
  93. {
  94. template<typename BasicJsonType>
  95. static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
  96. {
  97. j.m_type = value_t::array;
  98. j.m_value = arr;
  99. j.assert_invariant();
  100. }
  101. template<typename BasicJsonType>
  102. static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
  103. {
  104. j.m_type = value_t::array;
  105. j.m_value = std::move(arr);
  106. j.assert_invariant();
  107. }
  108. template<typename BasicJsonType, typename CompatibleArrayType,
  109. enable_if_t<not std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
  110. int> = 0>
  111. static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
  112. {
  113. using std::begin;
  114. using std::end;
  115. j.m_type = value_t::array;
  116. j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
  117. j.assert_invariant();
  118. }
  119. template<typename BasicJsonType>
  120. static void construct(BasicJsonType& j, const std::vector<bool>& arr)
  121. {
  122. j.m_type = value_t::array;
  123. j.m_value = value_t::array;
  124. j.m_value.array->reserve(arr.size());
  125. for (const bool x : arr)
  126. {
  127. j.m_value.array->push_back(x);
  128. }
  129. j.assert_invariant();
  130. }
  131. template<typename BasicJsonType, typename T,
  132. enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
  133. static void construct(BasicJsonType& j, const std::valarray<T>& arr)
  134. {
  135. j.m_type = value_t::array;
  136. j.m_value = value_t::array;
  137. j.m_value.array->resize(arr.size());
  138. std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
  139. j.assert_invariant();
  140. }
  141. };
  142. template<>
  143. struct external_constructor<value_t::object>
  144. {
  145. template<typename BasicJsonType>
  146. static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
  147. {
  148. j.m_type = value_t::object;
  149. j.m_value = obj;
  150. j.assert_invariant();
  151. }
  152. template<typename BasicJsonType>
  153. static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
  154. {
  155. j.m_type = value_t::object;
  156. j.m_value = std::move(obj);
  157. j.assert_invariant();
  158. }
  159. template<typename BasicJsonType, typename CompatibleObjectType,
  160. enable_if_t<not std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int> = 0>
  161. static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
  162. {
  163. using std::begin;
  164. using std::end;
  165. j.m_type = value_t::object;
  166. j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
  167. j.assert_invariant();
  168. }
  169. };
  170. /////////////
  171. // to_json //
  172. /////////////
  173. template<typename BasicJsonType, typename T,
  174. enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
  175. void to_json(BasicJsonType& j, T b) noexcept
  176. {
  177. external_constructor<value_t::boolean>::construct(j, b);
  178. }
  179. template<typename BasicJsonType, typename CompatibleString,
  180. enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
  181. void to_json(BasicJsonType& j, const CompatibleString& s)
  182. {
  183. external_constructor<value_t::string>::construct(j, s);
  184. }
  185. template<typename BasicJsonType>
  186. void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
  187. {
  188. external_constructor<value_t::string>::construct(j, std::move(s));
  189. }
  190. template<typename BasicJsonType, typename FloatType,
  191. enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
  192. void to_json(BasicJsonType& j, FloatType val) noexcept
  193. {
  194. external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
  195. }
  196. template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
  197. enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
  198. void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
  199. {
  200. external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
  201. }
  202. template<typename BasicJsonType, typename CompatibleNumberIntegerType,
  203. enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
  204. void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
  205. {
  206. external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
  207. }
  208. template<typename BasicJsonType, typename EnumType,
  209. enable_if_t<std::is_enum<EnumType>::value, int> = 0>
  210. void to_json(BasicJsonType& j, EnumType e) noexcept
  211. {
  212. using underlying_type = typename std::underlying_type<EnumType>::type;
  213. external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
  214. }
  215. template<typename BasicJsonType>
  216. void to_json(BasicJsonType& j, const std::vector<bool>& e)
  217. {
  218. external_constructor<value_t::array>::construct(j, e);
  219. }
  220. template<typename BasicJsonType, typename CompatibleArrayType,
  221. enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value or
  222. std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value,
  223. int> = 0>
  224. void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
  225. {
  226. external_constructor<value_t::array>::construct(j, arr);
  227. }
  228. template<typename BasicJsonType, typename T,
  229. enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
  230. void to_json(BasicJsonType& j, const std::valarray<T>& arr)
  231. {
  232. external_constructor<value_t::array>::construct(j, std::move(arr));
  233. }
  234. template<typename BasicJsonType>
  235. void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
  236. {
  237. external_constructor<value_t::array>::construct(j, std::move(arr));
  238. }
  239. template<typename BasicJsonType, typename CompatibleObjectType,
  240. enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0>
  241. void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
  242. {
  243. external_constructor<value_t::object>::construct(j, obj);
  244. }
  245. template<typename BasicJsonType>
  246. void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
  247. {
  248. external_constructor<value_t::object>::construct(j, std::move(obj));
  249. }
  250. template<typename BasicJsonType, typename T, std::size_t N,
  251. enable_if_t<not std::is_constructible<typename BasicJsonType::string_t, T (&)[N]>::value, int> = 0>
  252. void to_json(BasicJsonType& j, T (&arr)[N])
  253. {
  254. external_constructor<value_t::array>::construct(j, arr);
  255. }
  256. template<typename BasicJsonType, typename... Args>
  257. void to_json(BasicJsonType& j, const std::pair<Args...>& p)
  258. {
  259. j = {p.first, p.second};
  260. }
  261. // for https://github.com/nlohmann/json/pull/1134
  262. template<typename BasicJsonType, typename T,
  263. enable_if_t<std::is_same<T, typename iteration_proxy<typename BasicJsonType::iterator>::iteration_proxy_internal>::value, int> = 0>
  264. void to_json(BasicJsonType& j, T b) noexcept
  265. {
  266. j = {{b.key(), b.value()}};
  267. }
  268. template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
  269. void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...>)
  270. {
  271. j = {std::get<Idx>(t)...};
  272. }
  273. template<typename BasicJsonType, typename... Args>
  274. void to_json(BasicJsonType& j, const std::tuple<Args...>& t)
  275. {
  276. to_json_tuple_impl(j, t, index_sequence_for<Args...> {});
  277. }
  278. struct to_json_fn
  279. {
  280. private:
  281. template<typename BasicJsonType, typename T>
  282. auto call(BasicJsonType& j, T&& val, priority_tag<1> /*unused*/) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
  283. -> decltype(to_json(j, std::forward<T>(val)), void())
  284. {
  285. return to_json(j, std::forward<T>(val));
  286. }
  287. template<typename BasicJsonType, typename T>
  288. void call(BasicJsonType& /*unused*/, T&& /*unused*/, priority_tag<0> /*unused*/) const noexcept
  289. {
  290. static_assert(sizeof(BasicJsonType) == 0,
  291. "could not find to_json() method in T's namespace");
  292. #ifdef _MSC_VER
  293. // MSVC does not show a stacktrace for the above assert
  294. using decayed = uncvref_t<T>;
  295. static_assert(sizeof(typename decayed::force_msvc_stacktrace) == 0,
  296. "forcing MSVC stacktrace to show which T we're talking about.");
  297. #endif
  298. }
  299. public:
  300. template<typename BasicJsonType, typename T>
  301. void operator()(BasicJsonType& j, T&& val) const
  302. noexcept(noexcept(std::declval<to_json_fn>().call(j, std::forward<T>(val), priority_tag<1> {})))
  303. {
  304. return call(j, std::forward<T>(val), priority_tag<1> {});
  305. }
  306. };
  307. }
  308. /// namespace to hold default `to_json` function
  309. namespace
  310. {
  311. constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;
  312. }
  313. }