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