Horizon
Loading...
Searching...
No Matches
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
17namespace nlohmann
18{
19namespace 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
32template<value_t> struct external_constructor;
33
34template<>
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
47template<>
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
80template<>
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
102template<>
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
115template<>
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
128template<>
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
141template<>
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
211template<>
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
253template<typename BasicJsonType, typename T,
254 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
255void to_json(BasicJsonType& j, T b) noexcept
256{
258}
259
260template<typename BasicJsonType, typename CompatibleString,
261 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
262void to_json(BasicJsonType& j, const CompatibleString& s)
263{
264 external_constructor<value_t::string>::construct(j, s);
265}
266
267template<typename BasicJsonType>
268void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
269{
270 external_constructor<value_t::string>::construct(j, std::move(s));
271}
272
273template<typename BasicJsonType, typename FloatType,
274 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
275void 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
280template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
281 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
282void 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
287template<typename BasicJsonType, typename CompatibleNumberIntegerType,
288 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
289void 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
294template<typename BasicJsonType, typename EnumType,
295 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
296void 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
302template<typename BasicJsonType>
303void to_json(BasicJsonType& j, const std::vector<bool>& e)
304{
305 external_constructor<value_t::array>::construct(j, e);
306}
307
308template < 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 >
316void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
317{
318 external_constructor<value_t::array>::construct(j, arr);
319}
320
321template<typename BasicJsonType>
322void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
323{
324 external_constructor<value_t::binary>::construct(j, bin);
325}
326
327template<typename BasicJsonType, typename T,
328 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
329void to_json(BasicJsonType& j, const std::valarray<T>& arr)
330{
331 external_constructor<value_t::array>::construct(j, std::move(arr));
332}
333
334template<typename BasicJsonType>
335void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
336{
337 external_constructor<value_t::array>::construct(j, std::move(arr));
338}
339
340template < typename BasicJsonType, typename CompatibleObjectType,
341 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
342void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
343{
344 external_constructor<value_t::object>::construct(j, obj);
345}
346
347template<typename BasicJsonType>
348void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
349{
350 external_constructor<value_t::object>::construct(j, std::move(obj));
351}
352
353template <
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 >
358void 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
363template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
364void 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
370template<typename BasicJsonType, typename T,
371 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
372void to_json(BasicJsonType& j, const T& b)
373{
374 j = { {b.key(), b.value()} };
375}
376
377template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
378void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
379{
380 j = { std::get<Idx>(t)... };
381}
382
383template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
384void 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
403namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
404{
405constexpr 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)
@ value
the parser finished reading a JSON value
namespace for Niels Lohmann
Definition adl_serializer.hpp:12
Definition cpp_future.hpp:146
Definition to_json.hpp:390