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