6 #include <forward_list>
10 #include <type_traits>
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>
24 template<
typename BasicJsonType,
typename ArithmeticType,
25 enable_if_t<std::is_arithmetic<ArithmeticType>::value and
26 not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
28 void get_arithmetic_value(
const BasicJsonType& j, ArithmeticType& val)
30 switch (static_cast<value_t>(j))
34 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
39 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
44 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
49 JSON_THROW(type_error::create(302,
"type must be number, but is " +
std::string(j.type_name())));
53 template<
typename BasicJsonType>
54 void from_json(
const BasicJsonType& j,
typename BasicJsonType::boolean_t& b)
56 if (JSON_UNLIKELY(not j.is_boolean()))
58 JSON_THROW(type_error::create(302,
"type must be boolean, but is " +
std::string(j.type_name())));
60 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
63 template<
typename BasicJsonType>
64 void from_json(
const BasicJsonType& j,
typename BasicJsonType::string_t& s)
66 if (JSON_UNLIKELY(not j.is_string()))
68 JSON_THROW(type_error::create(302,
"type must be string, but is " +
std::string(j.type_name())));
70 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
73 template<
typename BasicJsonType>
74 void from_json(
const BasicJsonType& j,
typename BasicJsonType::number_float_t& val)
76 get_arithmetic_value(j, val);
79 template<
typename BasicJsonType>
80 void from_json(
const BasicJsonType& j,
typename BasicJsonType::number_unsigned_t& val)
82 get_arithmetic_value(j, val);
85 template<
typename BasicJsonType>
86 void from_json(
const BasicJsonType& j,
typename BasicJsonType::number_integer_t& val)
88 get_arithmetic_value(j, val);
91 template<
typename BasicJsonType,
typename EnumType,
92 enable_if_t<std::is_enum<EnumType>::value,
int> = 0>
93 void from_json(
const BasicJsonType& j, EnumType& e)
95 typename std::underlying_type<EnumType>::type val;
96 get_arithmetic_value(j, val);
97 e = static_cast<EnumType>(val);
100 template<
typename BasicJsonType>
101 void from_json(
const BasicJsonType& j,
typename BasicJsonType::array_t& arr)
103 if (JSON_UNLIKELY(not j.is_array()))
105 JSON_THROW(type_error::create(302,
"type must be array, but is " +
std::string(j.type_name())));
107 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
111 template<
typename BasicJsonType,
typename T,
typename Allocator,
112 enable_if_t<std::is_convertible<BasicJsonType, T>::value,
int> = 0>
113 void from_json(
const BasicJsonType& j, std::forward_list<T, Allocator>& l)
115 if (JSON_UNLIKELY(not j.is_array()))
117 JSON_THROW(type_error::create(302,
"type must be array, but is " +
std::string(j.type_name())));
119 std::transform(j.rbegin(), j.rend(),
120 std::front_inserter(l), [](
const BasicJsonType & i)
122 return i.template get<T>();
127 template<
typename BasicJsonType,
typename T,
128 enable_if_t<std::is_convertible<BasicJsonType, T>::value,
int> = 0>
129 void from_json(
const BasicJsonType& j, std::valarray<T>& l)
131 if (JSON_UNLIKELY(not j.is_array()))
133 JSON_THROW(type_error::create(302,
"type must be array, but is " +
std::string(j.type_name())));
136 std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l));
139 template<
typename BasicJsonType,
typename CompatibleArrayType>
140 void from_json_array_impl(
const BasicJsonType& j, CompatibleArrayType& arr,
priority_tag<0> )
144 std::transform(j.begin(), j.end(),
145 std::inserter(arr, end(arr)), [](
const BasicJsonType & i)
149 return i.template get<typename CompatibleArrayType::value_type>();
153 template<
typename BasicJsonType,
typename CompatibleArrayType>
154 auto from_json_array_impl(
const BasicJsonType& j, CompatibleArrayType& arr,
priority_tag<1> )
156 arr.reserve(std::declval<typename CompatibleArrayType::size_type>()),
161 arr.reserve(j.size());
162 std::transform(j.begin(), j.end(),
163 std::inserter(arr, end(arr)), [](
const BasicJsonType & i)
167 return i.template get<typename CompatibleArrayType::value_type>();
171 template<
typename BasicJsonType,
typename T, std::
size_t N>
172 void from_json_array_impl(
const BasicJsonType& j, std::array<T, N>& arr,
priority_tag<2> )
174 for (std::size_t i = 0; i < N; ++i)
176 arr[i] = j.at(i).template get<T>();
180 template<
typename BasicJsonType,
typename CompatibleArrayType,
181 enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and
182 std::is_convertible<BasicJsonType, typename CompatibleArrayType::value_type>::value and
183 not std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value,
int> = 0>
184 void from_json(
const BasicJsonType& j, CompatibleArrayType& arr)
186 if (JSON_UNLIKELY(not j.is_array()))
188 JSON_THROW(type_error::create(302,
"type must be array, but is " +
std::string(j.type_name())));
194 template<
typename BasicJsonType,
typename CompatibleObjectType,
195 enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value,
int> = 0>
196 void from_json(
const BasicJsonType& j, CompatibleObjectType& obj)
198 if (JSON_UNLIKELY(not j.is_object()))
200 JSON_THROW(type_error::create(302,
"type must be object, but is " +
std::string(j.type_name())));
203 auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
204 using value_type =
typename CompatibleObjectType::value_type;
206 inner_object->begin(), inner_object->end(),
207 std::inserter(obj, obj.begin()),
208 [](
typename BasicJsonType::object_t::value_type
const & p)
210 return value_type(p.first, p.second.template get<typename CompatibleObjectType::mapped_type>());
218 template<
typename BasicJsonType,
typename ArithmeticType,
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,
226 void from_json(
const BasicJsonType& j, ArithmeticType& val)
228 switch (static_cast<value_t>(j))
232 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
237 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
242 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
247 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
252 JSON_THROW(type_error::create(302,
"type must be number, but is " +
std::string(j.type_name())));
256 template<
typename BasicJsonType,
typename A1,
typename A2>
257 void from_json(
const BasicJsonType& j, std::pair<A1, A2>& p)
259 p = {j.at(0).template get<A1>(), j.at(1).template get<A2>()};
262 template<
typename BasicJsonType,
typename Tuple, std::size_t... Idx>
265 t = std::make_tuple(j.at(Idx).template get<typename std::tuple_element<Idx, Tuple>::type>()...);
268 template<
typename BasicJsonType,
typename... Args>
269 void from_json(
const BasicJsonType& j, std::tuple<Args...>& t)
277 template<
typename BasicJsonType,
typename T>
279 noexcept(noexcept(from_json(j, val)))
280 -> decltype(from_json(j, val),
void())
282 return from_json(j, val);
285 template<
typename BasicJsonType,
typename T>
288 static_assert(
sizeof(BasicJsonType) == 0,
289 "could not find from_json() method in T's namespace");
292 using decayed = uncvref_t<T>;
293 static_assert(
sizeof(
typename decayed::force_msvc_stacktrace) == 0,
294 "forcing MSVC stacktrace to show which T we're talking about.");
299 template<
typename BasicJsonType,
typename T>
300 void operator()(
const BasicJsonType& j, T& val)
const
301 noexcept(noexcept(std::declval<from_json_fn>().call(j, val,
priority_tag<1> {})))