from_json.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. #pragma once
  2. #include <algorithm> // transform
  3. #include <array> // array
  4. #include <ciso646> // and, not
  5. #include <forward_list> // forward_list
  6. #include <iterator> // inserter, front_inserter, end
  7. #include <map> // map
  8. #include <string> // string
  9. #include <tuple> // tuple, make_tuple
  10. #include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
  11. #include <unordered_map> // unordered_map
  12. #include <utility> // pair, declval
  13. #include <valarray> // valarray
  14. #include <nlohmann/detail/exceptions.hpp>
  15. #include <nlohmann/detail/macro_scope.hpp>
  16. #include <nlohmann/detail/meta.hpp>
  17. #include <nlohmann/detail/value_t.hpp>
  18. namespace nlohmann
  19. {
  20. namespace detail
  21. {
  22. // overloads for basic_json template parameters
  23. template<typename BasicJsonType, typename ArithmeticType,
  24. enable_if_t<std::is_arithmetic<ArithmeticType>::value and
  25. not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
  26. int> = 0>
  27. void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
  28. {
  29. switch (static_cast<value_t>(j))
  30. {
  31. case value_t::number_unsigned:
  32. {
  33. val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
  34. break;
  35. }
  36. case value_t::number_integer:
  37. {
  38. val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
  39. break;
  40. }
  41. case value_t::number_float:
  42. {
  43. val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
  44. break;
  45. }
  46. default:
  47. JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
  48. }
  49. }
  50. template<typename BasicJsonType>
  51. void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
  52. {
  53. if (JSON_UNLIKELY(not j.is_boolean()))
  54. {
  55. JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name())));
  56. }
  57. b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
  58. }
  59. template<typename BasicJsonType>
  60. void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
  61. {
  62. if (JSON_UNLIKELY(not j.is_string()))
  63. {
  64. JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
  65. }
  66. s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
  67. }
  68. template <
  69. typename BasicJsonType, typename CompatibleStringType,
  70. enable_if_t <
  71. is_compatible_string_type<BasicJsonType, CompatibleStringType>::value and
  72. not std::is_same<typename BasicJsonType::string_t,
  73. CompatibleStringType>::value,
  74. int > = 0 >
  75. void from_json(const BasicJsonType& j, CompatibleStringType& s)
  76. {
  77. if (JSON_UNLIKELY(not j.is_string()))
  78. {
  79. JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
  80. }
  81. s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
  82. }
  83. template<typename BasicJsonType>
  84. void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
  85. {
  86. get_arithmetic_value(j, val);
  87. }
  88. template<typename BasicJsonType>
  89. void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
  90. {
  91. get_arithmetic_value(j, val);
  92. }
  93. template<typename BasicJsonType>
  94. void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
  95. {
  96. get_arithmetic_value(j, val);
  97. }
  98. template<typename BasicJsonType, typename EnumType,
  99. enable_if_t<std::is_enum<EnumType>::value, int> = 0>
  100. void from_json(const BasicJsonType& j, EnumType& e)
  101. {
  102. typename std::underlying_type<EnumType>::type val;
  103. get_arithmetic_value(j, val);
  104. e = static_cast<EnumType>(val);
  105. }
  106. template<typename BasicJsonType>
  107. void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr)
  108. {
  109. if (JSON_UNLIKELY(not j.is_array()))
  110. {
  111. JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
  112. }
  113. arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
  114. }
  115. // forward_list doesn't have an insert method
  116. template<typename BasicJsonType, typename T, typename Allocator,
  117. enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
  118. void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
  119. {
  120. if (JSON_UNLIKELY(not j.is_array()))
  121. {
  122. JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
  123. }
  124. std::transform(j.rbegin(), j.rend(),
  125. std::front_inserter(l), [](const BasicJsonType & i)
  126. {
  127. return i.template get<T>();
  128. });
  129. }
  130. // valarray doesn't have an insert method
  131. template<typename BasicJsonType, typename T,
  132. enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
  133. void from_json(const BasicJsonType& j, std::valarray<T>& l)
  134. {
  135. if (JSON_UNLIKELY(not j.is_array()))
  136. {
  137. JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
  138. }
  139. l.resize(j.size());
  140. std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l));
  141. }
  142. template<typename BasicJsonType, typename CompatibleArrayType>
  143. void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0> /*unused*/)
  144. {
  145. using std::end;
  146. std::transform(j.begin(), j.end(),
  147. std::inserter(arr, end(arr)), [](const BasicJsonType & i)
  148. {
  149. // get<BasicJsonType>() returns *this, this won't call a from_json
  150. // method when value_type is BasicJsonType
  151. return i.template get<typename CompatibleArrayType::value_type>();
  152. });
  153. }
  154. template<typename BasicJsonType, typename CompatibleArrayType>
  155. auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1> /*unused*/)
  156. -> decltype(
  157. arr.reserve(std::declval<typename CompatibleArrayType::size_type>()),
  158. void())
  159. {
  160. using std::end;
  161. arr.reserve(j.size());
  162. std::transform(j.begin(), j.end(),
  163. std::inserter(arr, end(arr)), [](const BasicJsonType & i)
  164. {
  165. // get<BasicJsonType>() returns *this, this won't call a from_json
  166. // method when value_type is BasicJsonType
  167. return i.template get<typename CompatibleArrayType::value_type>();
  168. });
  169. }
  170. template<typename BasicJsonType, typename T, std::size_t N>
  171. void from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr, priority_tag<2> /*unused*/)
  172. {
  173. for (std::size_t i = 0; i < N; ++i)
  174. {
  175. arr[i] = j.at(i).template get<T>();
  176. }
  177. }
  178. template <
  179. typename BasicJsonType, typename CompatibleArrayType,
  180. enable_if_t <
  181. is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and
  182. not std::is_same<typename BasicJsonType::array_t,
  183. CompatibleArrayType>::value and
  184. std::is_constructible <
  185. BasicJsonType, typename CompatibleArrayType::value_type >::value,
  186. int > = 0 >
  187. void from_json(const BasicJsonType& j, CompatibleArrayType& arr)
  188. {
  189. if (JSON_UNLIKELY(not j.is_array()))
  190. {
  191. JSON_THROW(type_error::create(302, "type must be array, but is " +
  192. std::string(j.type_name())));
  193. }
  194. from_json_array_impl(j, arr, priority_tag<2> {});
  195. }
  196. template<typename BasicJsonType, typename CompatibleObjectType,
  197. enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0>
  198. void from_json(const BasicJsonType& j, CompatibleObjectType& obj)
  199. {
  200. if (JSON_UNLIKELY(not j.is_object()))
  201. {
  202. JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name())));
  203. }
  204. auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
  205. using value_type = typename CompatibleObjectType::value_type;
  206. std::transform(
  207. inner_object->begin(), inner_object->end(),
  208. std::inserter(obj, obj.begin()),
  209. [](typename BasicJsonType::object_t::value_type const & p)
  210. {
  211. return value_type(p.first, p.second.template get<typename CompatibleObjectType::mapped_type>());
  212. });
  213. }
  214. // overload for arithmetic types, not chosen for basic_json template arguments
  215. // (BooleanType, etc..); note: Is it really necessary to provide explicit
  216. // overloads for boolean_t etc. in case of a custom BooleanType which is not
  217. // an arithmetic type?
  218. template<typename BasicJsonType, typename ArithmeticType,
  219. enable_if_t <
  220. std::is_arithmetic<ArithmeticType>::value and
  221. not std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and
  222. not std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and
  223. not std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and
  224. not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
  225. int> = 0>
  226. void from_json(const BasicJsonType& j, ArithmeticType& val)
  227. {
  228. switch (static_cast<value_t>(j))
  229. {
  230. case value_t::number_unsigned:
  231. {
  232. val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
  233. break;
  234. }
  235. case value_t::number_integer:
  236. {
  237. val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
  238. break;
  239. }
  240. case value_t::number_float:
  241. {
  242. val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
  243. break;
  244. }
  245. case value_t::boolean:
  246. {
  247. val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
  248. break;
  249. }
  250. default:
  251. JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
  252. }
  253. }
  254. template<typename BasicJsonType, typename A1, typename A2>
  255. void from_json(const BasicJsonType& j, std::pair<A1, A2>& p)
  256. {
  257. p = {j.at(0).template get<A1>(), j.at(1).template get<A2>()};
  258. }
  259. template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
  260. void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence<Idx...>)
  261. {
  262. t = std::make_tuple(j.at(Idx).template get<typename std::tuple_element<Idx, Tuple>::type>()...);
  263. }
  264. template<typename BasicJsonType, typename... Args>
  265. void from_json(const BasicJsonType& j, std::tuple<Args...>& t)
  266. {
  267. from_json_tuple_impl(j, t, index_sequence_for<Args...> {});
  268. }
  269. template <typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
  270. typename = enable_if_t<not std::is_constructible<
  271. typename BasicJsonType::string_t, Key>::value>>
  272. void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
  273. {
  274. if (JSON_UNLIKELY(not j.is_array()))
  275. {
  276. JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
  277. }
  278. for (const auto& p : j)
  279. {
  280. if (JSON_UNLIKELY(not p.is_array()))
  281. {
  282. JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
  283. }
  284. m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
  285. }
  286. }
  287. template <typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
  288. typename = enable_if_t<not std::is_constructible<
  289. typename BasicJsonType::string_t, Key>::value>>
  290. void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
  291. {
  292. if (JSON_UNLIKELY(not j.is_array()))
  293. {
  294. JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
  295. }
  296. for (const auto& p : j)
  297. {
  298. if (JSON_UNLIKELY(not p.is_array()))
  299. {
  300. JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
  301. }
  302. m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
  303. }
  304. }
  305. struct from_json_fn
  306. {
  307. private:
  308. template<typename BasicJsonType, typename T>
  309. auto call(const BasicJsonType& j, T& val, priority_tag<1> /*unused*/) const
  310. noexcept(noexcept(from_json(j, val)))
  311. -> decltype(from_json(j, val), void())
  312. {
  313. return from_json(j, val);
  314. }
  315. template<typename BasicJsonType, typename T>
  316. void call(const BasicJsonType& /*unused*/, T& /*unused*/, priority_tag<0> /*unused*/) const noexcept
  317. {
  318. static_assert(sizeof(BasicJsonType) == 0,
  319. "could not find from_json() method in T's namespace");
  320. #ifdef _MSC_VER
  321. // MSVC does not show a stacktrace for the above assert
  322. using decayed = uncvref_t<T>;
  323. static_assert(sizeof(typename decayed::force_msvc_stacktrace) == 0,
  324. "forcing MSVC stacktrace to show which T we're talking about.");
  325. #endif
  326. }
  327. public:
  328. template<typename BasicJsonType, typename T>
  329. void operator()(const BasicJsonType& j, T& val) const
  330. noexcept(noexcept(std::declval<from_json_fn>().call(j, val, priority_tag<1> {})))
  331. {
  332. return call(j, val, priority_tag<1> {});
  333. }
  334. };
  335. }
  336. /// namespace to hold default `from_json` function
  337. /// to see why this is required:
  338. /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
  339. namespace
  340. {
  341. constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value;
  342. }
  343. }