Reflection for RapidJSON  0.0.12
Reflection for serializing/deserializing with RapidJSON
reflector.h
Go to the documentation of this file.
1 #ifndef REFLECTIVE_RAPIDJSON_JSON_REFLECTOR_H
2 #define REFLECTIVE_RAPIDJSON_JSON_REFLECTOR_H
3 
10 #include "../traits.h"
11 
12 #include <c++utilities/application/global.h>
13 
14 #include <rapidjson/document.h>
15 #include <rapidjson/rapidjson.h>
16 #include <rapidjson/stringbuffer.h>
17 #include <rapidjson/writer.h>
18 
19 #include <limits>
20 #include <map>
21 #include <memory>
22 #include <set>
23 #include <string>
24 #include <tuple>
25 #include <unordered_map>
26 #include <unordered_set>
27 #include <variant>
28 
29 #include "./errorhandling.h"
30 
31 namespace ReflectiveRapidJSON {
32 
33 template <typename Type> struct JsonSerializable;
34 
38 template <typename T> struct AdaptedJsonSerializable : public Traits::Bool<false> {
39  static constexpr const char *name = "AdaptedJsonSerializable";
40  static constexpr const char *qualifiedName = "ReflectiveRapidJSON::AdaptedJsonSerializable";
41 };
42 
46 namespace JsonReflector {
47 
51 constexpr RAPIDJSON_NAMESPACE::SizeType rapidJsonSize(std::size_t size)
52 {
53  return size > std::numeric_limits<RAPIDJSON_NAMESPACE::SizeType>::max() ? std::numeric_limits<RAPIDJSON_NAMESPACE::SizeType>::max()
54  : static_cast<RAPIDJSON_NAMESPACE::SizeType>(size);
55 }
56 
60 inline RAPIDJSON_NAMESPACE::StringBuffer serializeJsonDocToString(RAPIDJSON_NAMESPACE::Document &document)
61 {
62  RAPIDJSON_NAMESPACE::StringBuffer buffer;
63  RAPIDJSON_NAMESPACE::Writer<RAPIDJSON_NAMESPACE::StringBuffer> writer(buffer);
64  document.Accept(writer);
65  return buffer;
66 }
67 
71 inline RAPIDJSON_NAMESPACE::Document parseJsonDocFromString(const char *json, std::size_t jsonSize)
72 {
73  RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kObjectType);
74  const RAPIDJSON_NAMESPACE::ParseResult parseRes = document.Parse(json, jsonSize);
75  if (parseRes.IsError()) {
76  throw parseRes;
77  }
78  return document;
79 }
80 
81 // define traits to distinguish between "built-in" types like int, std::string, std::vector, ... and custom structs/classes
82 template <typename Type>
83 using IsBuiltInType = Traits::Any<std::is_integral<Type>, std::is_floating_point<Type>, std::is_pointer<Type>, std::is_enum<Type>,
84  Traits::IsSpecializationOf<Type, std::tuple>, Traits::IsSpecializationOf<Type, std::pair>, Traits::IsIteratable<Type>,
85  Traits::IsSpecializationOf<Type, std::unique_ptr>, Traits::IsSpecializationOf<Type, std::shared_ptr>,
86  Traits::IsSpecializationOf<Type, std::weak_ptr>, IsVariant<Type>>;
87 template <typename Type> using IsCustomType = Traits::Not<IsBuiltInType<Type>>;
88 
89 // define trait to check for custom structs/classes which are JSON serializable
90 // NOTE: the check for Traits::IsComplete is required because std::is_base_of fails for incomplete types when using GCC
91 template <typename Type>
93  = Traits::Any<Traits::Not<Traits::IsComplete<Type>>, std::is_base_of<JsonSerializable<Type>, Type>, AdaptedJsonSerializable<Type>>;
94 
95 // define functions to "push" values to a RapidJSON array or object
96 
100 template <typename Type, Traits::DisableIf<IsBuiltInType<Type>> * = nullptr>
101 void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator);
102 
106 template <typename Type, Traits::DisableIf<IsJsonSerializable<Type>> * = nullptr>
107 void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value::Array &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator);
108 
112 template <typename Type, Traits::EnableIf<IsJsonSerializable<Type>> * = nullptr>
113 void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value::Array &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator);
114 
118 template <typename Type, Traits::EnableIf<IsJsonSerializable<Type>> * = nullptr>
119 void push(
120  const Type &reflectable, const char *name, RAPIDJSON_NAMESPACE::Value::Object &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator);
121 
125 template <typename Type, Traits::DisableIf<IsJsonSerializable<Type>> * = nullptr>
126 void push(
127  const Type &reflectable, const char *name, RAPIDJSON_NAMESPACE::Value::Object &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator);
128 
133 template <typename Type, Traits::DisableIf<IsBuiltInType<Type>> * = nullptr>
134 void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value::Object &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator);
135 
139 template <typename Type, Traits::DisableIf<IsBuiltInType<Type>> *>
140 inline void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
141 {
142  value.SetObject();
143  RAPIDJSON_NAMESPACE::Value::Object obj(value.GetObject());
144  push(reflectable, obj, allocator);
145 }
146 
150 template <typename Type, Traits::EnableIfAny<std::is_integral<Type>, std::is_floating_point<Type>> * = nullptr>
151 inline void push(Type reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
152 {
153  value.Set(reflectable, allocator);
154 }
155 
159 template <typename Type, Traits::EnableIfAny<std::is_enum<Type>> * = nullptr>
160 inline void push(Type reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
161 {
162  value.Set(static_cast<Traits::Conditional<std::is_unsigned<typename std::underlying_type<Type>::type>, std::uint64_t, std::int64_t>>(reflectable),
163  allocator);
164 }
165 
169 template <typename Type, Traits::EnableIf<std::is_same<Type, const char *>> * = nullptr>
170 inline void push(Type reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
171 {
172  value.SetString(RAPIDJSON_NAMESPACE::StringRef(reflectable), allocator);
173 }
174 
178 template <typename Type, Traits::EnableIf<std::is_same<Type, const char *const &>> * = nullptr>
179 inline void push(const char *const &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
180 {
181  value.SetString(RAPIDJSON_NAMESPACE::StringRef(reflectable), allocator);
182 }
183 
187 template <typename Type, Traits::EnableIf<std::is_same<Type, std::string>> * = nullptr>
188 inline void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
189 {
190  value.SetString(RAPIDJSON_NAMESPACE::StringRef(reflectable.data(), reflectable.size()), allocator);
191 }
192 
196 template <typename Type, Traits::EnableIf<IsArrayOrSet<Type>, Traits::HasSize<Type>> * = nullptr>
197 void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
198 {
199  value.SetArray();
200  RAPIDJSON_NAMESPACE::Value::Array array(value.GetArray());
201  array.Reserve(reflectable.size(), allocator);
202  for (const auto &item : reflectable) {
203  push(item, array, allocator);
204  }
205 }
206 
210 template <typename Type, Traits::EnableIf<IsArrayOrSet<Type>, Traits::Not<Traits::HasSize<Type>>> * = nullptr>
211 void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
212 {
213  value.SetArray();
214  RAPIDJSON_NAMESPACE::Value::Array array(value.GetArray());
215  for (const auto &item : reflectable) {
216  push(item, array, allocator);
217  }
218 }
219 
223 template <typename Type, Traits::EnableIfAny<IsMapOrHash<Type>> * = nullptr>
224 void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
225 {
226  value.SetObject();
227  RAPIDJSON_NAMESPACE::Value::Object object(value.GetObject());
228  for (const auto &item : reflectable) {
229  push(item.second, item.first.data(), object, allocator);
230  }
231 }
232 
236 template <typename Type, Traits::EnableIfAny<IsMultiMapOrHash<Type>> * = nullptr>
237 void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
238 {
239  value.SetObject();
240  for (const auto &item : reflectable) {
241  const auto memberName = RAPIDJSON_NAMESPACE::Value::StringRefType(item.first.data(), rapidJsonSize(item.first.size()));
242  const auto existingMember = value.FindMember(memberName);
243  const auto arrayAlreadyExists
244  = existingMember != value.MemberEnd() && existingMember->value.GetType() == RAPIDJSON_NAMESPACE::Type::kArrayType;
245  auto newArrayValue = RAPIDJSON_NAMESPACE::Value{ RAPIDJSON_NAMESPACE::kArrayType };
246  RAPIDJSON_NAMESPACE::Value::Array array = arrayAlreadyExists ? existingMember->value.GetArray() : newArrayValue.GetArray();
247  push(item.second, array, allocator);
248  if (!arrayAlreadyExists) {
249  value.AddMember(memberName, newArrayValue, allocator);
250  }
251  }
252 }
253 
254 namespace Detail {
255 
259 template <class Tuple, std::size_t N> struct TuplePushHelper {
260  static void push(const Tuple &tuple, RAPIDJSON_NAMESPACE::Value::Array &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
261  {
262  TuplePushHelper<Tuple, N - 1>::push(tuple, value, allocator);
263  JsonReflector::push(std::get<N - 1>(tuple), value, allocator);
264  }
265 };
266 
267 template <class Tuple> struct TuplePushHelper<Tuple, 1> {
268  static void push(const Tuple &tuple, RAPIDJSON_NAMESPACE::Value::Array &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
269  {
270  JsonReflector::push(std::get<0>(tuple), value, allocator);
271  }
272 };
273 } // namespace Detail
274 
278 template <typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::tuple>> * = nullptr>
279 void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
280 {
281  value.SetArray();
282  RAPIDJSON_NAMESPACE::Value::Array array(value.GetArray());
283  array.Reserve(std::tuple_size<Type>::value, allocator);
284  Detail::TuplePushHelper<Type, std::tuple_size<Type>::value>::push(reflectable, array, allocator);
285 }
286 
290 template <typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::pair>> * = nullptr>
291 void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
292 {
293  value.SetArray();
294  RAPIDJSON_NAMESPACE::Value::Array array(value.GetArray());
295  array.Reserve(2, allocator);
296  push(reflectable.first, array, allocator);
297  push(reflectable.second, array, allocator);
298 }
299 
303 template <typename Type,
304  Traits::EnableIfAny<Traits::IsSpecializationOf<Type, std::unique_ptr>, Traits::IsSpecializationOf<Type, std::shared_ptr>,
305  Traits::IsSpecializationOf<Type, std::weak_ptr>> * = nullptr>
306 void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
307 {
308  if (!reflectable) {
309  value.SetNull();
310  return;
311  }
312  push(*reflectable, value, allocator);
313 }
314 
318 template <typename Type, Traits::EnableIf<IsVariant<Type>> * = nullptr>
319 void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
320 {
321  if (reflectable.valueless_by_exception()) {
322  value.SetNull();
323  return;
324  }
325 
326  RAPIDJSON_NAMESPACE::Value index, data;
327  index.SetInt(reflectable.index());
328  std::visit(
329  [&data, &allocator](const auto &reflectableOfActualType) {
330  if constexpr (!std::is_same_v<std::decay_t<decltype(reflectableOfActualType)>, std::monostate>) {
331  push(reflectableOfActualType, data, allocator);
332  } else {
333  CPP_UTILITIES_UNUSED(data)
334  CPP_UTILITIES_UNUSED(allocator)
335  }
336  },
337  reflectable);
338 
339  value.SetObject();
340  value.AddMember("index", index, allocator);
341  value.AddMember("data", data, allocator);
342 }
343 
347 template <typename Type, Traits::EnableIf<IsJsonSerializable<Type>> *>
348 void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value::Array &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
349 {
350  RAPIDJSON_NAMESPACE::Value objectValue(RAPIDJSON_NAMESPACE::kObjectType);
351  RAPIDJSON_NAMESPACE::Value::Object object(objectValue.GetObject());
352  push(reflectable, object, allocator);
353  value.PushBack(objectValue, allocator);
354 }
355 
359 template <typename Type, Traits::DisableIf<IsJsonSerializable<Type>> *>
360 void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value::Array &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
361 {
362  RAPIDJSON_NAMESPACE::Value genericValue;
363  push(reflectable, genericValue, allocator);
364  value.PushBack(genericValue, allocator);
365 }
366 
370 template <typename Type, Traits::EnableIf<IsJsonSerializable<Type>> *>
371 void push(
372  const Type &reflectable, const char *name, RAPIDJSON_NAMESPACE::Value::Object &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
373 {
374  RAPIDJSON_NAMESPACE::Value objectValue(RAPIDJSON_NAMESPACE::kObjectType);
375  RAPIDJSON_NAMESPACE::Value::Object object(objectValue.GetObject());
376  push(reflectable, object, allocator);
377  value.AddMember(RAPIDJSON_NAMESPACE::StringRef(name), objectValue, allocator);
378 }
379 
383 template <typename Type, Traits::DisableIf<IsJsonSerializable<Type>> *>
384 void push(
385  const Type &reflectable, const char *name, RAPIDJSON_NAMESPACE::Value::Object &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
386 {
387  RAPIDJSON_NAMESPACE::Value genericValue;
388  push(reflectable, genericValue, allocator);
389  value.AddMember(RAPIDJSON_NAMESPACE::StringRef(name), genericValue, allocator);
390 }
391 
392 // define functions to "pull" values from a RapidJSON array or object
393 
398 template <typename Type, Traits::DisableIf<IsBuiltInType<Type>> * = nullptr>
399 void pull(Type &reflectable, const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>>::ConstObject &value,
400  JsonDeserializationErrors *errors);
401 
405 template <typename Type, Traits::DisableIf<IsBuiltInType<Type>> * = nullptr>
406 void pull(Type &reflectable, const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
407 
411 template <typename Type, Traits::EnableIf<IsArrayOrSet<Type>, Traits::Not<Traits::IsReservable<Type>>> * = nullptr>
412 void pull(Type &reflectable, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
413 
417 template <typename Type, Traits::EnableIf<IsArrayOrSet<Type>, Traits::IsReservable<Type>> * = nullptr>
418 void pull(Type &reflectable, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
419 
423 template <typename Type, Traits::EnableIf<IsArray<Type>> * = nullptr>
424 void pull(Type &reflectable, rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>>::ConstArray array, JsonDeserializationErrors *errors);
425 
429 template <typename Type, Traits::EnableIf<IsSet<Type>> * = nullptr>
430 void pull(Type &reflectable, rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>>::ConstArray array, JsonDeserializationErrors *errors);
431 
435 template <typename Type, Traits::EnableIf<IsMultiSet<Type>> * = nullptr>
436 void pull(Type &reflectable, rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>>::ConstArray array, JsonDeserializationErrors *errors);
437 
441 template <typename Type, Traits::EnableIf<IsMapOrHash<Type>> * = nullptr>
442 void pull(Type &reflectable, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
443 
447 template <typename Type, Traits::EnableIf<IsMultiMapOrHash<Type>> * = nullptr>
448 void pull(Type &reflectable, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
449 
453 template <typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::tuple>> * = nullptr>
454 void pull(Type &reflectable, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
455 
459 template <typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::pair>> * = nullptr>
460 void pull(Type &reflectable, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
461 
465 template <typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::unique_ptr>> * = nullptr>
466 void pull(Type &reflectable, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
467 
471 template <typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::shared_ptr>> * = nullptr>
472 void pull(Type &reflectable, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
473 
477 template <typename Type, Traits::EnableIf<IsVariant<Type>> * = nullptr>
478 void pull(Type &reflectable, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
479 
483 template <typename Type>
484 inline void pull(
485  Type &reflectable, rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>>::ValueIterator &value, JsonDeserializationErrors *errors);
486 
492 template <typename Type>
493 inline void pull(Type &reflectable, const char *name, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>>::ConstObject &value,
494  JsonDeserializationErrors *errors);
495 
499 template <typename Type, Traits::DisableIf<IsBuiltInType<Type>> *>
500 void pull(Type &reflectable, const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
501 
505 template <typename Type,
506  Traits::EnableIf<Traits::Not<std::is_same<Type, bool>>, Traits::Any<std::is_integral<Type>, std::is_floating_point<Type>>> * = nullptr>
507 inline void pull(
508  Type &reflectable, const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
509 {
510  if (!value.IsNumber()) {
511  if (errors) {
512  errors->reportTypeMismatch<Type>(value.GetType());
513  }
514  return;
515  }
516  reflectable = value.Is<Type>() ? value.Get<Type>() : static_cast<Type>(value.GetDouble());
517 }
518 
522 template <typename Type, Traits::EnableIf<std::is_same<Type, bool>> * = nullptr>
523 inline void pull(
524  Type &reflectable, const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
525 {
526  if (!value.IsBool()) {
527  if (errors) {
528  errors->reportTypeMismatch<Type>(value.GetType());
529  }
530  return;
531  }
532  reflectable = value.GetBool();
533 }
534 
539 template <typename Type, Traits::EnableIfAny<std::is_enum<Type>> * = nullptr>
540 inline void pull(
541  Type &reflectable, const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
542 {
543  using ExpectedType = Traits::Conditional<std::is_unsigned<typename std::underlying_type<Type>::type>, std::uint64_t, std::int64_t>;
544  if (!value.Is<ExpectedType>()) {
545  if (errors) {
546  errors->reportTypeMismatch<ExpectedType>(value.GetType());
547  }
548  return;
549  }
550  reflectable = static_cast<Type>(value.Get<ExpectedType>());
551 }
552 
556 template <typename Type, Traits::EnableIf<std::is_same<Type, std::string>> * = nullptr>
557 inline void pull(
558  Type &reflectable, const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
559 {
560  if (!value.IsString()) {
561  if (errors) {
562  errors->reportTypeMismatch<std::string>(value.GetType());
563  }
564  return;
565  }
566  reflectable = value.GetString();
567 }
568 
573 template <typename Type, Traits::EnableIfAny<std::is_same<Type, const char *>, std::is_same<Type, const char *const &>> * = nullptr>
574 inline void pull(Type &, const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
575 {
576  if (!value.IsString()) {
577  if (errors) {
578  errors->reportTypeMismatch<std::string>(value.GetType());
579  }
580  return;
581  }
582 }
583 
587 template <typename Type, Traits::EnableIf<IsArrayOrSet<Type>, Traits::Not<Traits::IsReservable<Type>>> *>
588 void pull(Type &reflectable, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
589 {
590  if (!value.IsArray()) {
591  if (errors) {
592  errors->reportTypeMismatch<Type>(value.GetType());
593  }
594  return;
595  }
596  pull(reflectable, value.GetArray(), errors);
597 }
598 
602 template <typename Type, Traits::EnableIf<IsArrayOrSet<Type>, Traits::IsReservable<Type>> *>
603 void pull(Type &reflectable, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
604 {
605  if (!value.IsArray()) {
606  if (errors) {
607  errors->reportTypeMismatch<Type>(value.GetType());
608  }
609  return;
610  }
611  auto array = value.GetArray();
612  reflectable.reserve(array.Size());
613  pull(reflectable, array, errors);
614 }
615 
619 template <typename Type, Traits::EnableIf<IsArray<Type>> *>
620 void pull(Type &reflectable, rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>>::ConstArray array, JsonDeserializationErrors *errors)
621 {
622  // clear previous contents of the array
623  reflectable.clear();
624 
625  // pull all array elements of the specified value
626  std::size_t index = 0;
627  for (const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &item : array) {
628  // set error context for current index
629  if (errors) {
630  errors->currentIndex = index;
631  }
632  ++index;
633  reflectable.emplace_back();
634  pull(reflectable.back(), item, errors);
635  }
636 
637  // clear error context
638  if (errors) {
640  }
641 }
642 
646 template <typename Type, Traits::EnableIf<IsMultiSet<Type>> *>
647 void pull(Type &reflectable, rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>>::ConstArray array, JsonDeserializationErrors *errors)
648 {
649  // clear previous contents of the array
650  reflectable.clear();
651 
652  // pull all array elements of the specified value
653  std::size_t index = 0;
654  for (const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &item : array) {
655  // set error context for current index
656  if (errors) {
657  errors->currentIndex = index;
658  }
659  ++index;
660  typename Type::value_type itemObj;
661  pull(itemObj, item, errors);
662  reflectable.emplace(move(itemObj));
663  }
664 
665  // clear error context
666  if (errors) {
668  }
669 }
670 
674 template <typename Type, Traits::EnableIf<IsSet<Type>> *>
675 void pull(Type &reflectable, rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>>::ConstArray array, JsonDeserializationErrors *errors)
676 {
677  // clear previous contents of the array
678  reflectable.clear();
679 
680  // pull all array elements of the specified value
681  std::size_t index = 0;
682  for (const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &item : array) {
683  // set error context for current index
684  if (errors) {
685  errors->currentIndex = index;
686  }
687  ++index;
688  typename Type::value_type itemObj;
689  pull(itemObj, item, errors);
690  if (!reflectable.emplace(move(itemObj)).second) {
691  errors->reportUnexpectedDuplicate(JsonType::Array);
692  }
693  }
694 
695  // clear error context
696  if (errors) {
697  errors->currentIndex = JsonDeserializationError::noIndex;
698  }
699 }
700 
704 template <typename Type, Traits::EnableIf<IsMapOrHash<Type>> *>
705 void pull(Type &reflectable, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
706 {
707  if (!value.IsObject()) {
708  if (errors) {
709  errors->reportTypeMismatch<Type>(value.GetType());
710  }
711  return;
712  }
713  auto obj = value.GetObject();
714  for (auto i = obj.MemberBegin(), end = obj.MemberEnd(); i != end; ++i) {
715  pull(reflectable[i->name.GetString()], i->value, errors);
716  }
717 }
718 
722 template <typename Type, Traits::EnableIf<IsMultiMapOrHash<Type>> *>
723 void pull(Type &reflectable, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
724 {
725  if (!value.IsObject()) {
726  if (errors) {
727  errors->reportTypeMismatch<Type>(value.GetType());
728  }
729  return;
730  }
731  auto obj = value.GetObject();
732  for (auto i = obj.MemberBegin(), end = obj.MemberEnd(); i != end; ++i) {
733  if (i->value.GetType() != RAPIDJSON_NAMESPACE::kArrayType) {
734  auto insertedIterator = reflectable.insert(typename Type::value_type(i->name.GetString(), typename Type::mapped_type()));
735  pull(insertedIterator->second, i->value, errors);
736  continue;
737  }
738  const auto array = i->value.GetArray();
739  for (const auto &value : array) {
740  auto insertedIterator = reflectable.insert(typename Type::value_type(i->name.GetString(), typename Type::mapped_type()));
741  pull(insertedIterator->second, value, errors);
742  }
743  }
744 }
745 
746 namespace Detail {
747 
752 template <class Tuple, std::size_t N> struct TuplePullHelper {
753  static void pull(Tuple &tuple, const RAPIDJSON_NAMESPACE::Value::ConstArray value, JsonDeserializationErrors *errors)
754  {
755  TuplePullHelper<Tuple, N - 1>::pull(tuple, value, errors);
756  JsonReflector::pull<typename std::tuple_element<N - 1, Tuple>::type>(std::get<N - 1>(tuple), value[N - 1], errors);
757  }
758 };
759 
760 template <class Tuple> struct TuplePullHelper<Tuple, 1> {
761  static void pull(Tuple &tuple, const RAPIDJSON_NAMESPACE::Value::ConstArray value, JsonDeserializationErrors *errors)
762  {
763  JsonReflector::pull<typename std::tuple_element<0, Tuple>::type>(std::get<0>(tuple), value[0], errors);
764  }
765 };
766 } // namespace Detail
767 
771 template <typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::tuple>> *>
772 void pull(Type &reflectable, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
773 {
774  if (!value.IsArray()) {
775  if (errors) {
776  errors->reportTypeMismatch<Type>(value.GetType());
777  }
778  return;
779  }
780  const auto array = value.GetArray();
781  if (array.Size() != std::tuple_size<Type>::value) {
782  if (errors) {
783  // FIXME: report expected and actual size
784  errors->reportArraySizeMismatch();
785  }
786  return;
787  }
788  Detail::TuplePullHelper<Type, std::tuple_size<Type>::value>::pull(reflectable, array, errors);
789 }
790 
794 template <typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::pair>> *>
795 void pull(Type &reflectable, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
796 {
797  if (!value.IsArray()) {
798  if (errors) {
799  errors->reportTypeMismatch<Type>(value.GetType());
800  }
801  return;
802  }
803  const auto array = value.GetArray();
804  if (array.Size() != 2) {
805  if (errors) {
806  // FIXME: report expected and actual size
807  errors->reportArraySizeMismatch();
808  }
809  return;
810  }
811  pull(reflectable.first, array[0], errors);
812  pull(reflectable.second, array[1], errors);
813 }
814 
818 template <typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::unique_ptr>> *>
819 void pull(Type &reflectable, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
820 {
821  if (value.IsNull()) {
822  reflectable.reset();
823  return;
824  }
825  reflectable = std::make_unique<typename Type::element_type>();
826  pull(*reflectable, value, errors);
827 }
828 
832 template <typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::shared_ptr>> *>
833 void pull(Type &reflectable, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
834 {
835  if (value.IsNull()) {
836  reflectable.reset();
837  return;
838  }
839  reflectable = std::make_shared<typename Type::element_type>();
840  pull(*reflectable, value, errors);
841 }
842 
844 namespace Detail {
845 template <typename Variant, std::size_t compiletimeIndex = 0>
846 void assignVariantValueByRuntimeIndex(std::size_t runtimeIndex, Variant &variant,
847  const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
848 {
849  if constexpr (compiletimeIndex < std::variant_size_v<Variant>) {
850  if (compiletimeIndex == runtimeIndex) {
851  if constexpr (std::is_same_v<std::variant_alternative_t<compiletimeIndex, Variant>, std::monostate>) {
852  variant = std::monostate{};
853  } else {
854  pull(variant.template emplace<compiletimeIndex>(), value, errors);
855  }
856  } else {
857  assignVariantValueByRuntimeIndex<Variant, compiletimeIndex + 1>(runtimeIndex, variant, value, errors);
858  }
859  } else {
860  if (errors) {
861  errors->emplace_back(JsonDeserializationErrorKind::InvalidVariantIndex, JsonType::Number, JsonType::Number, errors->currentRecord,
862  errors->currentMember, errors->currentIndex);
863  }
864  }
865 }
866 } // namespace Detail
868 
872 template <typename Type, Traits::EnableIf<IsVariant<Type>> *>
873 void pull(Type &reflectable, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
874 {
875  if (!value.IsObject()) {
876  if (errors) {
877  errors->reportTypeMismatch<Type>(value.GetType());
878  }
879  return;
880  }
881 
882  auto obj = value.GetObject();
883  auto indexIterator = obj.FindMember("index");
884  auto dataIterator = obj.FindMember("data");
885  if (indexIterator == obj.MemberEnd() || dataIterator == obj.MemberEnd()) {
886  if (errors) {
887  errors->emplace_back(JsonDeserializationErrorKind::InvalidVariantObject, JsonType::Object, JsonType::Object, errors->currentRecord,
888  errors->currentMember, errors->currentIndex);
889  }
890  return;
891  }
892  const auto &indexValue = indexIterator->value;
893  if (!indexValue.IsInt()) {
894  if (errors) {
895  errors->emplace_back(JsonDeserializationErrorKind::InvalidVariantIndex, JsonType::Number, jsonType(indexValue.GetType()),
896  errors->currentRecord, errors->currentMember, errors->currentIndex);
897  }
898  return;
899  }
900  const auto index = indexValue.GetInt();
901  if (index < 0) {
902  errors->emplace_back(JsonDeserializationErrorKind::InvalidVariantIndex, JsonType::Number, JsonType::Number, errors->currentRecord,
903  errors->currentMember, errors->currentIndex);
904  return;
905  }
906  Detail::assignVariantValueByRuntimeIndex(static_cast<std::size_t>(index), reflectable, dataIterator->value, errors);
907 }
908 
912 template <typename Type>
913 inline void pull(Type &reflectable, rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>>::ValueIterator &value, JsonDeserializationErrors *errors)
914 {
915  pull<Type>(reflectable, *value, errors);
916  ++value;
917 }
918 
924 template <typename Type>
925 inline void pull(Type &reflectable, const char *name, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>>::ConstObject &value,
927 {
928  // find member
929  const auto member = value.FindMember(name);
930  if (member == value.MemberEnd()) {
931  return; // TODO: handle member missing
932  }
933 
934  // set error context for current member
935  const char *previousMember;
936  if (errors) {
937  previousMember = errors->currentMember;
938  errors->currentMember = name;
939  }
940 
941  // actually pull value for member
942  pull<Type>(reflectable, member->value, errors);
943 
944  // restore previous error context
945  if (errors) {
946  errors->currentMember = previousMember;
947  }
948 }
949 
953 template <typename Type, Traits::DisableIf<IsBuiltInType<Type>> *>
954 void pull(Type &reflectable, const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
955 {
956  if (!value.IsObject()) {
957  if (errors) {
958  errors->reportTypeMismatch<Type>(value.GetType());
959  }
960  return;
961  }
962  pull(reflectable, value.GetObject(), errors);
963 }
964 
965 // define functions providing high-level JSON serialization
966 
970 template <typename Type, Traits::EnableIfAny<IsJsonSerializable<Type>, IsMapOrHash<Type>, IsMultiMapOrHash<Type>> * = nullptr>
971 RAPIDJSON_NAMESPACE::Document toJsonDocument(const Type &reflectable)
972 {
973  RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kObjectType);
974  push(reflectable, document, document.GetAllocator());
975  return document;
976 }
977 
981 template <typename Type, Traits::EnableIfAny<std::is_integral<Type>, std::is_floating_point<Type>> * = nullptr>
982 RAPIDJSON_NAMESPACE::Document toJsonDocument(Type reflectable)
983 {
984  RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kNumberType);
985  document.Set(reflectable, document.GetAllocator());
986  return document;
987 }
988 
992 template <typename Type, Traits::EnableIf<std::is_same<Type, std::string>> * = nullptr>
993 RAPIDJSON_NAMESPACE::Document toJsonDocument(const std::string &reflectable)
994 {
995  RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kStringType);
996  document.SetString(RAPIDJSON_NAMESPACE::StringRef(reflectable.data(), reflectable.size()), document.GetAllocator());
997  return document;
998 }
999 
1003 template <typename Type, Traits::EnableIf<std::is_same<Type, const char *>> * = nullptr>
1004 RAPIDJSON_NAMESPACE::Document toJsonDocument(const char *reflectable)
1005 {
1006  RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kStringType);
1007  document.SetString(RAPIDJSON_NAMESPACE::StringRef(reflectable), document.GetAllocator());
1008  return document;
1009 }
1010 
1014 template <typename Type, Traits::EnableIf<IsArray<Type>> * = nullptr> RAPIDJSON_NAMESPACE::Document toJsonDocument(const Type &reflectable)
1015 {
1016  RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kArrayType);
1017  push(reflectable, document, document.GetAllocator());
1018  return document;
1019 }
1020 
1024 template <typename Type,
1025  Traits::EnableIfAny<IsJsonSerializable<Type>, IsMapOrHash<Type>, IsMultiMapOrHash<Type>, std::is_integral<Type>, std::is_floating_point<Type>,
1026  Traits::IsString<Type>, IsArray<Type>> * = nullptr>
1027 RAPIDJSON_NAMESPACE::StringBuffer toJson(const Type &reflectable)
1028 {
1029  auto document(toJsonDocument(reflectable));
1030  return serializeJsonDocToString(document);
1031 }
1032 
1033 // define functions providing high-level JSON deserialization
1034 
1038 template <typename Type, Traits::EnableIfAny<IsJsonSerializable<Type>, IsMapOrHash<Type>, IsMultiMapOrHash<Type>> * = nullptr>
1039 Type fromJson(const char *json, std::size_t jsonSize, JsonDeserializationErrors *errors = nullptr)
1040 {
1041  RAPIDJSON_NAMESPACE::Document doc(parseJsonDocFromString(json, jsonSize));
1042  if (!doc.IsObject()) {
1043  if (errors) {
1044  errors->reportTypeMismatch<Type>(doc.GetType());
1045  }
1046  return Type();
1047  }
1048 
1049  Type res;
1050  pull<Type>(res, doc.GetObject(), errors);
1051  return res;
1052 }
1053 
1057 template <typename Type, Traits::EnableIfAny<std::is_integral<Type>, std::is_floating_point<Type>> * = nullptr>
1058 Type fromJson(const char *json, std::size_t jsonSize, JsonDeserializationErrors *errors = nullptr)
1059 {
1060  RAPIDJSON_NAMESPACE::Document doc(parseJsonDocFromString(json, jsonSize));
1061  if (!doc.Is<Type>()) {
1062  if (errors) {
1063  errors->reportTypeMismatch<Type>(doc.GetType());
1064  }
1065  return Type();
1066  }
1067 
1068  return doc.Get<Type>();
1069 }
1070 
1074 template <typename Type, Traits::EnableIf<std::is_same<Type, std::string>> * = nullptr>
1075 Type fromJson(const char *json, std::size_t jsonSize, JsonDeserializationErrors *errors = nullptr)
1076 {
1077  RAPIDJSON_NAMESPACE::Document doc(parseJsonDocFromString(json, jsonSize));
1078  if (!doc.IsString()) {
1079  if (errors) {
1080  errors->reportTypeMismatch<Type>(doc.GetType());
1081  }
1082  return Type();
1083  }
1084 
1085  return doc.GetString();
1086 }
1087 
1091 template <typename Type, Traits::EnableIf<IsArray<Type>> * = nullptr>
1092 Type fromJson(const char *json, std::size_t jsonSize, JsonDeserializationErrors *errors = nullptr)
1093 {
1094  RAPIDJSON_NAMESPACE::Document doc(parseJsonDocFromString(json, jsonSize));
1095  if (!doc.IsArray()) {
1096  if (errors) {
1097  errors->reportTypeMismatch<Type>(doc.GetType());
1098  }
1099  return Type();
1100  }
1101 
1102  Type res;
1103  pull<Type>(res, doc.GetArray(), errors);
1104  return res;
1105 }
1106 
1110 template <typename Type> Type fromJson(const char *json, JsonDeserializationErrors *errors = nullptr)
1111 {
1112  return fromJson<Type>(json, std::strlen(json), errors);
1113 }
1114 
1118 template <typename Type> Type fromJson(const std::string &json, JsonDeserializationErrors *errors = nullptr)
1119 {
1120  return fromJson<Type>(json.data(), json.size(), errors);
1121 }
1122 
1123 } // namespace JsonReflector
1124 } // namespace ReflectiveRapidJSON
1125 
1126 #endif // REFLECTIVE_RAPIDJSON_JSON_REFLECTOR_H
ReflectiveRapidJSON::JsonDeserializationErrors
The JsonDeserializationErrors struct can be passed to fromJson() for error handling.
Definition: errorhandling.h:154
ReflectiveRapidJSON::AdaptedJsonSerializable::qualifiedName
static constexpr const char * qualifiedName
Definition: reflector.h:40
ReflectiveRapidJSON::JsonReflector::fromJson
Type fromJson(const char *json, std::size_t jsonSize, JsonDeserializationErrors *errors=nullptr)
Deserializes the specified JSON to.
Definition: reflector.h:1039
ReflectiveRapidJSON::JsonDeserializationErrorKind::InvalidVariantIndex
@ InvalidVariantIndex
ReflectiveRapidJSON::JsonReflector::pull
void pull(Type &reflectable, const RAPIDJSON_NAMESPACE::GenericValue< RAPIDJSON_NAMESPACE::UTF8< char >>::ConstObject &value, JsonDeserializationErrors *errors)
Pulls the reflectable which has a custom type from the specified object.
Definition: reflector-boosthana.h:40
ReflectiveRapidJSON::JsonReflector::rapidJsonSize
constexpr RAPIDJSON_NAMESPACE::SizeType rapidJsonSize(std::size_t size)
Casts the specified size to the size type used by RapidJSON ensuring no overflow happens.
Definition: reflector.h:51
ReflectiveRapidJSON::AdaptedJsonSerializable::name
static constexpr const char * name
Definition: reflector.h:39
ReflectiveRapidJSON::JsonReflector::Detail::TuplePullHelper
The TuplePullHelper class helps deserializing tuples from JSON arrays.
Definition: reflector.h:752
ReflectiveRapidJSON::jsonType
constexpr JsonType jsonType()
Definition: errorhandling.h:50
ReflectiveRapidJSON::JsonReflector::toJson
RAPIDJSON_NAMESPACE::StringBuffer toJson(const Type &reflectable)
Serializes the specified reflectable.
Definition: reflector.h:1027
ReflectiveRapidJSON::JsonDeserializationErrors::currentIndex
std::size_t currentIndex
The index in the array which is currently processed.
Definition: errorhandling.h:167
errorhandling.h
Contains helper for error handling when deserializing JSON files.
ReflectiveRapidJSON::JsonReflector::IsCustomType
Traits::Not< IsBuiltInType< Type > > IsCustomType
Definition: reflector.h:87
ReflectiveRapidJSON
Definition: traits.h:13
ReflectiveRapidJSON::JsonDeserializationErrors::currentMember
const char * currentMember
The name of the member (in currentRecord) which is currently being processed.
Definition: errorhandling.h:165
ReflectiveRapidJSON::JsonReflector::Detail::TuplePushHelper::push
static void push(const Tuple &tuple, RAPIDJSON_NAMESPACE::Value::Array &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
Definition: reflector.h:260
ReflectiveRapidJSON::JsonReflector::Detail::TuplePushHelper< Tuple, 1 >::push
static void push(const Tuple &tuple, RAPIDJSON_NAMESPACE::Value::Array &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
Definition: reflector.h:268
ReflectiveRapidJSON::JsonReflector::IsJsonSerializable
Traits::Any< Traits::Not< Traits::IsComplete< Type > >, std::is_base_of< JsonSerializable< Type >, Type >, AdaptedJsonSerializable< Type > > IsJsonSerializable
Definition: reflector.h:93
ReflectiveRapidJSON::JsonDeserializationErrors::reportArraySizeMismatch
void reportArraySizeMismatch()
Reports an array size mismatch.
Definition: errorhandling.h:228
ReflectiveRapidJSON::JsonReflector::IsBuiltInType
Traits::Any< std::is_integral< Type >, std::is_floating_point< Type >, std::is_pointer< Type >, std::is_enum< Type >, Traits::IsSpecializationOf< Type, std::tuple >, Traits::IsSpecializationOf< Type, std::pair >, Traits::IsIteratable< Type >, Traits::IsSpecializationOf< Type, std::unique_ptr >, Traits::IsSpecializationOf< Type, std::shared_ptr >, Traits::IsSpecializationOf< Type, std::weak_ptr >, IsVariant< Type > > IsBuiltInType
Definition: reflector.h:86
ReflectiveRapidJSON::JsonDeserializationError::noIndex
static constexpr std::size_t noIndex
Indicates no array was being processed when the error occured.
Definition: errorhandling.h:127
ReflectiveRapidJSON::JsonReflector::parseJsonDocFromString
RAPIDJSON_NAMESPACE::Document parseJsonDocFromString(const char *json, std::size_t jsonSize)
Parses the specified JSON string.
Definition: reflector.h:71
ReflectiveRapidJSON::JsonType::Array
@ Array
ReflectiveRapidJSON::JsonReflector::push
void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
Pushes the specified reflectable to the specified value.
Definition: reflector.h:140
ReflectiveRapidJSON::JsonDeserializationErrorKind::InvalidVariantObject
@ InvalidVariantObject
ReflectiveRapidJSON::JsonReflector::serializeJsonDocToString
RAPIDJSON_NAMESPACE::StringBuffer serializeJsonDocToString(RAPIDJSON_NAMESPACE::Document &document)
Serializes the specified JSON document.
Definition: reflector.h:60
ReflectiveRapidJSON::JsonSerializable
The JsonSerializable class provides the CRTP-base for (de)serializable objects.
Definition: reflector.h:33
ReflectiveRapidJSON::JsonReflector::Detail::TuplePushHelper
The TuplePushHelper class helps serializing tuples to JSON arrays.
Definition: reflector.h:259
ReflectiveRapidJSON::IsVariant
Traits::All< Traits::IsSpecializationOf< Type, std::variant > > IsVariant
Definition: traits.h:65
ReflectiveRapidJSON::JsonReflector::Detail::TuplePullHelper< Tuple, 1 >::pull
static void pull(Tuple &tuple, const RAPIDJSON_NAMESPACE::Value::ConstArray value, JsonDeserializationErrors *errors)
Definition: reflector.h:761
ReflectiveRapidJSON::JsonDeserializationErrors::reportTypeMismatch
void reportTypeMismatch(RAPIDJSON_NAMESPACE::Type presentType)
Reports a type mismatch between.
Definition: errorhandling.h:216
ReflectiveRapidJSON::AdaptedJsonSerializable
The AdaptedJsonSerializable class allows considering 3rd party classes as serializable.
Definition: reflector.h:38
ReflectiveRapidJSON::JsonReflector::toJsonDocument
RAPIDJSON_NAMESPACE::Document toJsonDocument(const Type &reflectable)
Serializes the specified reflectable which has a custom type or can be mapped to and object.
Definition: reflector.h:971
ReflectiveRapidJSON::JsonReflector::Detail::TuplePullHelper::pull
static void pull(Tuple &tuple, const RAPIDJSON_NAMESPACE::Value::ConstArray value, JsonDeserializationErrors *errors)
Definition: reflector.h:753
ReflectiveRapidJSON::JsonType::Number
@ Number
ReflectiveRapidJSON::JsonType::Object
@ Object