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