1 #ifndef REFLECTIVE_RAPIDJSON_JSON_REFLECTOR_H
2 #define REFLECTIVE_RAPIDJSON_JSON_REFLECTOR_H
10 #include "../traits.h"
12 #include <c++utilities/application/global.h>
14 #include <rapidjson/document.h>
15 #include <rapidjson/rapidjson.h>
16 #include <rapidjson/stringbuffer.h>
17 #include <rapidjson/writer.h>
25 #include <unordered_map>
26 #include <unordered_set>
39 static constexpr
const char *
name =
"AdaptedJsonSerializable";
40 static constexpr
const char *
qualifiedName =
"ReflectiveRapidJSON::AdaptedJsonSerializable";
46 namespace JsonReflector {
53 return size > std::numeric_limits<RAPIDJSON_NAMESPACE::SizeType>::max() ? std::numeric_limits<RAPIDJSON_NAMESPACE::SizeType>::max()
54 :
static_cast<RAPIDJSON_NAMESPACE::SizeType
>(size);
62 RAPIDJSON_NAMESPACE::StringBuffer buffer;
63 RAPIDJSON_NAMESPACE::Writer<RAPIDJSON_NAMESPACE::StringBuffer> writer(buffer);
64 document.Accept(writer);
73 RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kObjectType);
74 const RAPIDJSON_NAMESPACE::ParseResult parseRes = document.Parse(json, jsonSize);
75 if (parseRes.IsError()) {
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>,
87 template <
typename Type>
using IsCustomType = Traits::Not<IsBuiltInType<Type>>;
91 template <
typename Type>
100 template <
typename Type, Traits::DisableIf<IsBuiltInType<Type>> * =
nullptr>
101 void push(
const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator);
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);
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);
118 template <
typename Type, Traits::EnableIf<IsJsonSerializable<Type>> * =
nullptr>
120 const Type &reflectable,
const char *name, RAPIDJSON_NAMESPACE::Value::Object &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator);
125 template <
typename Type, Traits::DisableIf<IsJsonSerializable<Type>> * =
nullptr>
127 const Type &reflectable,
const char *name, RAPIDJSON_NAMESPACE::Value::Object &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator);
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);
139 template <
typename Type, Traits::DisableIf<IsBuiltInType<Type>> *>
140 inline void push(
const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
143 RAPIDJSON_NAMESPACE::Value::Object obj(value.GetObject());
144 push(reflectable, obj, allocator);
150 template <
typename Type, Traits::EnableIfAny<std::is_
integral<Type>, std::is_
floating_po
int<Type>> * =
nullptr>
151 inline void push(Type reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
153 value.Set(reflectable, allocator);
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)
162 value.Set(
static_cast<Traits::Conditional<std::is_unsigned<typename std::underlying_type<Type>::type
>, std::uint64_t, std::int64_t>>(reflectable),
169 template <
typename Type, Traits::EnableIfAny<std::is_same<Type, const
char *>, std::is_same<Type, const
char *const &>> * =
nullptr>
170 inline void push(Type reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
173 value.SetString(reflectable, allocator);
182 template <
typename Type, Traits::EnableIf<std::is_same<Type, std::
string_view>> * =
nullptr>
183 inline void push(Type reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
185 if (reflectable.data()) {
186 value.SetString(reflectable.data(),
rapidJsonSize(reflectable.size()), allocator);
195 template <
typename Type, Traits::EnableIf<std::is_same<Type, std::
string>> * =
nullptr>
196 inline void push(
const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
198 value.SetString(reflectable.data(),
rapidJsonSize(reflectable.size()), allocator);
204 template <
typename Type, Traits::EnableIf<IsArrayOrSet<Type>, Traits::HasSize<Type>> * =
nullptr>
205 void push(
const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
208 RAPIDJSON_NAMESPACE::Value::Array array(value.GetArray());
209 array.Reserve(reflectable.size(), allocator);
210 for (
const auto &item : reflectable) {
211 push(item, array, allocator);
218 template <
typename Type, Traits::EnableIf<IsArrayOrSet<Type>, Traits::Not<Traits::HasSize<Type>>> * =
nullptr>
219 void push(
const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
222 RAPIDJSON_NAMESPACE::Value::Array array(value.GetArray());
223 for (
const auto &item : reflectable) {
224 push(item, array, allocator);
231 template <
typename Type, Traits::EnableIfAny<IsMapOrHash<Type>> * =
nullptr>
232 void push(
const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
235 RAPIDJSON_NAMESPACE::Value::Object object(value.GetObject());
236 for (
const auto &item : reflectable) {
237 push(item.second, item.first.data(),
object, allocator);
244 template <
typename Type, Traits::EnableIfAny<IsMultiMapOrHash<Type>> * =
nullptr>
245 void push(
const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
248 for (
const auto &item : reflectable) {
249 const auto memberName = RAPIDJSON_NAMESPACE::Value::StringRefType(item.first.data(),
rapidJsonSize(item.first.size()));
250 const auto existingMember = value.FindMember(memberName);
251 const auto arrayAlreadyExists
252 = existingMember != value.MemberEnd() && existingMember->value.GetType() == RAPIDJSON_NAMESPACE::Type::kArrayType;
253 auto newArrayValue = RAPIDJSON_NAMESPACE::Value{ RAPIDJSON_NAMESPACE::kArrayType };
254 RAPIDJSON_NAMESPACE::Value::Array array = arrayAlreadyExists ? existingMember->value.GetArray() : newArrayValue.GetArray();
255 push(item.second, array, allocator);
256 if (!arrayAlreadyExists) {
257 value.AddMember(memberName, newArrayValue, allocator);
268 static void push(
const Tuple &tuple, RAPIDJSON_NAMESPACE::Value::Array &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
276 static void push(
const Tuple &tuple, RAPIDJSON_NAMESPACE::Value::Array &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
286 template <
typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::tuple>> * =
nullptr>
287 void push(
const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
290 RAPIDJSON_NAMESPACE::Value::Array array(value.GetArray());
291 array.Reserve(std::tuple_size<Type>::value, allocator);
292 Detail::TuplePushHelper<Type, std::tuple_size<Type>::value>
::push(reflectable, array, allocator);
298 template <
typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::pair>> * =
nullptr>
299 void push(
const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
302 RAPIDJSON_NAMESPACE::Value::Array array(value.GetArray());
303 array.Reserve(2, allocator);
304 push(reflectable.first, array, allocator);
305 push(reflectable.second, array, allocator);
311 template <
typename Type,
312 Traits::EnableIfAny<Traits::IsSpecializationOf<Type, std::unique_ptr>, Traits::IsSpecializationOf<Type, std::shared_ptr>,
313 Traits::IsSpecializationOf<Type, std::weak_ptr>> * =
nullptr>
314 void push(
const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
320 push(*reflectable, value, allocator);
326 template <
typename Type, Traits::EnableIf<IsVariant<Type>> * =
nullptr>
327 void push(
const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
329 if (reflectable.valueless_by_exception()) {
334 RAPIDJSON_NAMESPACE::Value index, data;
335 index.SetInt(reflectable.index());
337 [&data, &allocator](
const auto &reflectableOfActualType) {
338 if constexpr (!std::is_same_v<std::decay_t<decltype(reflectableOfActualType)>, std::monostate>) {
339 push(reflectableOfActualType, data, allocator);
341 CPP_UTILITIES_UNUSED(data)
342 CPP_UTILITIES_UNUSED(allocator)
348 value.AddMember(
"index", index, allocator);
349 value.AddMember(
"data", data, allocator);
355 template <
typename Type, Traits::EnableIf<IsJsonSerializable<Type>> *>
356 void push(
const Type &reflectable, RAPIDJSON_NAMESPACE::Value::Array &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
358 RAPIDJSON_NAMESPACE::Value objectValue(RAPIDJSON_NAMESPACE::kObjectType);
359 RAPIDJSON_NAMESPACE::Value::Object object(objectValue.GetObject());
360 push(reflectable,
object, allocator);
361 value.PushBack(objectValue, allocator);
367 template <
typename Type, Traits::DisableIf<IsJsonSerializable<Type>> *>
368 void push(
const Type &reflectable, RAPIDJSON_NAMESPACE::Value::Array &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
370 RAPIDJSON_NAMESPACE::Value genericValue;
371 push(reflectable, genericValue, allocator);
372 value.PushBack(genericValue, allocator);
378 template <
typename Type, Traits::EnableIf<IsJsonSerializable<Type>> *>
380 const Type &reflectable,
const char *name, RAPIDJSON_NAMESPACE::Value::Object &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
382 RAPIDJSON_NAMESPACE::Value objectValue(RAPIDJSON_NAMESPACE::kObjectType);
383 RAPIDJSON_NAMESPACE::Value::Object object(objectValue.GetObject());
384 push(reflectable,
object, allocator);
385 value.AddMember(RAPIDJSON_NAMESPACE::StringRef(name), objectValue, allocator);
391 template <
typename Type, Traits::DisableIf<IsJsonSerializable<Type>> *>
393 const Type &reflectable,
const char *name, RAPIDJSON_NAMESPACE::Value::Object &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
395 RAPIDJSON_NAMESPACE::Value genericValue;
396 push(reflectable, genericValue, allocator);
397 value.AddMember(RAPIDJSON_NAMESPACE::StringRef(name), genericValue, allocator);
406 template <
typename Type, Traits::DisableIf<IsBuiltInType<Type>> * =
nullptr>
407 void pull(Type &reflectable,
const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>>::ConstObject &value,
408 JsonDeserializationErrors *errors);
413 template <
typename Type, Traits::DisableIf<IsBuiltInType<Type>> * =
nullptr>
414 void pull(Type &reflectable,
const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
419 template <
typename Type, Traits::EnableIf<IsArrayOrSet<Type>, Traits::Not<Traits::IsReservable<Type>>> * =
nullptr>
420 void pull(Type &reflectable,
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
425 template <
typename Type, Traits::EnableIf<IsArrayOrSet<Type>, Traits::IsReservable<Type>> * =
nullptr>
426 void pull(Type &reflectable,
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
431 template <
typename Type, Traits::EnableIf<IsArray<Type>> * =
nullptr>
432 void pull(Type &reflectable, rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>>::ConstArray array, JsonDeserializationErrors *errors);
437 template <
typename Type, Traits::EnableIf<IsSet<Type>> * =
nullptr>
438 void pull(Type &reflectable, rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>>::ConstArray array, JsonDeserializationErrors *errors);
443 template <
typename Type, Traits::EnableIf<IsMultiSet<Type>> * =
nullptr>
444 void pull(Type &reflectable, rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>>::ConstArray array, JsonDeserializationErrors *errors);
449 template <
typename Type, Traits::EnableIf<IsMapOrHash<Type>> * =
nullptr>
450 void pull(Type &reflectable,
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
455 template <
typename Type, Traits::EnableIf<IsMultiMapOrHash<Type>> * =
nullptr>
456 void pull(Type &reflectable,
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
461 template <
typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::tuple>> * =
nullptr>
462 void pull(Type &reflectable,
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
467 template <
typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::pair>> * =
nullptr>
468 void pull(Type &reflectable,
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
473 template <
typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::unique_ptr>> * =
nullptr>
474 void pull(Type &reflectable,
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
479 template <
typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::shared_ptr>> * =
nullptr>
480 void pull(Type &reflectable,
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
485 template <
typename Type, Traits::EnableIf<IsVariant<Type>> * =
nullptr>
486 void pull(Type &reflectable,
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
491 template <
typename Type>
493 Type &reflectable, rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>>::ValueIterator &value, JsonDeserializationErrors *errors);
500 template <
typename Type>
501 inline void pull(Type &reflectable,
const char *name,
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>>::ConstObject &value,
502 JsonDeserializationErrors *errors);
507 template <
typename Type, Traits::DisableIf<IsBuiltInType<Type>> *>
508 void pull(Type &reflectable,
const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
513 template <
typename Type,
514 Traits::EnableIf<Traits::Not<std::is_same<Type, bool>>, Traits::Any<std::is_integral<Type>, std::is_floating_point<Type>>> * =
nullptr>
516 Type &reflectable,
const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value,
JsonDeserializationErrors *errors)
518 if (!value.IsNumber()) {
524 reflectable = value.Is<Type>() ? value.Get<Type>() :
static_cast<Type
>(value.GetDouble());
530 template <
typename Type, Traits::EnableIf<std::is_same<Type,
bool>> * =
nullptr>
532 Type &reflectable,
const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value,
JsonDeserializationErrors *errors)
534 if (!value.IsBool()) {
540 reflectable = value.GetBool();
547 template <
typename Type, Traits::EnableIfAny<std::is_enum<Type>> * =
nullptr>
549 Type &reflectable,
const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
551 using ExpectedType = Traits::Conditional<std::is_unsigned<typename std::underlying_type<Type>::type>, std::uint64_t, std::int64_t>;
552 if (!value.Is<ExpectedType>()) {
554 errors->reportTypeMismatch<ExpectedType>(value.GetType());
558 reflectable =
static_cast<Type
>(value.Get<ExpectedType>());
564 template <
typename Type, Traits::EnableIf<std::is_same<Type, std::
string>> * =
nullptr>
566 Type &reflectable,
const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
568 if (!value.IsString()) {
570 errors->reportTypeMismatch<std::string>(value.GetType());
574 reflectable = value.GetString();
581 template <
typename Type,
582 Traits::EnableIfAny<std::is_same<Type, const char *>, std::is_same<Type, const char *const &>, std::is_same<Type, std::string_view>> * =
nullptr>
583 inline void pull(Type &,
const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
585 if (!value.IsString()) {
587 errors->reportTypeMismatch<std::string>(value.GetType());
596 template <
typename Type, Traits::EnableIf<IsArrayOrSet<Type>, Traits::Not<Traits::IsReservable<Type>>> *>
599 if (!value.IsArray()) {
605 pull(reflectable, value.GetArray(), errors);
611 template <
typename Type, Traits::EnableIf<IsArrayOrSet<Type>, Traits::IsReservable<Type>> *>
614 if (!value.IsArray()) {
620 auto array = value.GetArray();
621 reflectable.reserve(array.Size());
622 pull(reflectable, array, errors);
628 template <
typename Type, Traits::EnableIf<IsArray<Type>> *>
635 std::size_t index = 0;
636 for (
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &item : array) {
642 reflectable.emplace_back();
643 pull(reflectable.back(), item, errors);
655 template <
typename Type, Traits::EnableIf<IsMultiSet<Type>> *>
662 std::size_t index = 0;
663 for (
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &item : array) {
669 typename Type::value_type itemObj;
670 pull(itemObj, item, errors);
671 reflectable.emplace(move(itemObj));
683 template <
typename Type, Traits::EnableIf<IsSet<Type>> *>
684 void pull(Type &reflectable, rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>>::ConstArray array, JsonDeserializationErrors *errors)
690 std::size_t index = 0;
691 for (
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &item : array) {
694 errors->currentIndex = index;
697 typename Type::value_type itemObj;
698 pull(itemObj, item, errors);
699 if (!reflectable.emplace(move(itemObj)).second) {
713 template <
typename Type, Traits::EnableIf<IsMapOrHash<Type>> *>
714 void pull(Type &reflectable,
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
716 if (!value.IsObject()) {
718 errors->reportTypeMismatch<Type>(value.GetType());
722 auto obj = value.GetObject();
723 for (
auto i = obj.MemberBegin(), end = obj.MemberEnd(); i != end; ++i) {
724 pull(reflectable[i->name.GetString()], i->value, errors);
731 template <
typename Type, Traits::EnableIf<IsMultiMapOrHash<Type>> *>
732 void pull(Type &reflectable,
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
734 if (!value.IsObject()) {
736 errors->reportTypeMismatch<Type>(value.GetType());
740 auto obj = value.GetObject();
741 for (
auto i = obj.MemberBegin(), end = obj.MemberEnd(); i != end; ++i) {
742 if (i->value.GetType() != RAPIDJSON_NAMESPACE::kArrayType) {
743 auto insertedIterator = reflectable.insert(
typename Type::value_type(i->name.GetString(),
typename Type::mapped_type()));
744 pull(insertedIterator->second, i->value, errors);
747 const auto array = i->value.GetArray();
748 for (
const auto &value : array) {
749 auto insertedIterator = reflectable.insert(
typename Type::value_type(i->name.GetString(),
typename Type::mapped_type()));
750 pull(insertedIterator->second, value, errors);
765 JsonReflector::pull<
typename std::tuple_element<N - 1, Tuple>::type>(std::get<N - 1>(tuple), value[N - 1], errors);
772 JsonReflector::pull<typename std::tuple_element<0, Tuple>::type>(std::get<0>(tuple), value[0], errors);
780 template <
typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::tuple>> *>
783 if (!value.IsArray()) {
789 const auto array = value.GetArray();
790 if (array.Size() != std::tuple_size<Type>::value) {
797 Detail::TuplePullHelper<Type, std::tuple_size<Type>::value>
::pull(reflectable, array, errors);
803 template <
typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::pair>> *>
804 void pull(Type &reflectable,
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
806 if (!value.IsArray()) {
808 errors->reportTypeMismatch<Type>(value.GetType());
812 const auto array = value.GetArray();
813 if (array.Size() != 2) {
816 errors->reportArraySizeMismatch();
820 pull(reflectable.first, array[0], errors);
821 pull(reflectable.second, array[1], errors);
827 template <
typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::unique_ptr>> *>
828 void pull(Type &reflectable,
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
830 if (value.IsNull()) {
834 reflectable = std::make_unique<typename Type::element_type>();
835 pull(*reflectable, value, errors);
841 template <
typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::shared_ptr>> *>
842 void pull(Type &reflectable,
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
844 if (value.IsNull()) {
848 reflectable = std::make_shared<typename Type::element_type>();
849 pull(*reflectable, value, errors);
854 template <
typename Variant, std::
size_t compiletimeIndex = 0>
855 void assignVariantValueByRuntimeIndex(std::size_t runtimeIndex, Variant &variant,
856 const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
858 if constexpr (compiletimeIndex < std::variant_size_v<Variant>) {
859 if (compiletimeIndex == runtimeIndex) {
860 if constexpr (std::is_same_v<std::variant_alternative_t<compiletimeIndex, Variant>, std::monostate>) {
861 variant = std::monostate{};
863 pull(variant.template emplace<compiletimeIndex>(), value, errors);
866 assignVariantValueByRuntimeIndex<Variant, compiletimeIndex + 1>(runtimeIndex, variant, value, errors);
871 errors->currentMember, errors->currentIndex);
881 template <
typename Type, Traits::EnableIf<IsVariant<Type>> *>
882 void pull(Type &reflectable,
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
884 if (!value.IsObject()) {
886 errors->reportTypeMismatch<Type>(value.GetType());
891 auto obj = value.GetObject();
892 auto indexIterator = obj.FindMember(
"index");
893 auto dataIterator = obj.FindMember(
"data");
894 if (indexIterator == obj.MemberEnd() || dataIterator == obj.MemberEnd()) {
897 errors->currentMember, errors->currentIndex);
901 const auto &indexValue = indexIterator->value;
902 if (!indexValue.IsInt()) {
905 errors->currentRecord, errors->currentMember, errors->currentIndex);
909 const auto index = indexValue.GetInt();
912 errors->currentMember, errors->currentIndex);
915 Detail::assignVariantValueByRuntimeIndex(
static_cast<std::size_t
>(index), reflectable, dataIterator->value, errors);
921 template <
typename Type>
924 pull<Type>(reflectable, *value, errors);
933 template <
typename Type>
934 inline void pull(Type &reflectable,
const char *name,
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>>::ConstObject &value,
938 const auto member = value.FindMember(name);
939 if (member == value.MemberEnd()) {
944 const char *previousMember;
951 pull<Type>(reflectable, member->value, errors);
962 template <
typename Type, Traits::DisableIf<IsBuiltInType<Type>> *>
963 void pull(Type &reflectable,
const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value,
JsonDeserializationErrors *errors)
965 if (!value.IsObject()) {
971 pull(reflectable, value.GetObject(), errors);
979 template <
typename Type, Traits::EnableIfAny<IsJsonSerializable<Type>, IsMapOrHash<Type>, IsMultiMapOrHash<Type>> * =
nullptr>
982 RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kObjectType);
983 push(reflectable, document, document.GetAllocator());
990 template <
typename Type, Traits::EnableIfAny<std::is_
integral<Type>, std::is_
floating_po
int<Type>> * =
nullptr>
993 RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kNumberType);
994 document.Set(reflectable, document.GetAllocator());
1001 template <
typename Type, Traits::EnableIf<std::is_same<Type, std::
string>> * =
nullptr>
1004 RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kStringType);
1005 document.SetString(RAPIDJSON_NAMESPACE::StringRef(reflectable.data(), reflectable.size()), document.GetAllocator());
1012 template <
typename Type, Traits::EnableIf<std::is_same<Type, const
char *>> * =
nullptr>
1015 RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kStringType);
1016 document.SetString(RAPIDJSON_NAMESPACE::StringRef(reflectable), document.GetAllocator());
1023 template <
typename Type, Traits::EnableIf<std::is_same<Type, std::
string_view>> * =
nullptr>
1026 RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kStringType);
1027 document.SetString(RAPIDJSON_NAMESPACE::StringRef(reflectable.data(), reflectable.size()), document.GetAllocator());
1034 template <
typename Type, Traits::EnableIf<IsArray<Type>> * =
nullptr> RAPIDJSON_NAMESPACE::Document
toJsonDocument(
const Type &reflectable)
1036 RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kArrayType);
1037 push(reflectable, document, document.GetAllocator());
1044 template <
typename Type,
1045 Traits::EnableIfAny<IsJsonSerializable<Type>, IsMapOrHash<Type>, IsMultiMapOrHash<Type>, std::is_integral<Type>, std::is_floating_point<Type>,
1046 Traits::IsString<Type>, IsArray<Type>> * =
nullptr>
1047 RAPIDJSON_NAMESPACE::StringBuffer
toJson(
const Type &reflectable)
1058 template <
typename Type, Traits::EnableIfAny<IsJsonSerializable<Type>, IsMapOrHash<Type>, IsMultiMapOrHash<Type>> * =
nullptr>
1062 if (!doc.IsObject()) {
1070 pull<Type>(res, doc.GetObject(), errors);
1077 template <
typename Type, Traits::EnableIfAny<std::is_
integral<Type>, std::is_
floating_po
int<Type>> * =
nullptr>
1081 if (!doc.Is<Type>()) {
1088 return doc.Get<Type>();
1094 template <
typename Type, Traits::EnableIf<std::is_same<Type, std::
string>> * =
nullptr>
1095 Type
fromJson(
const char *json, std::size_t jsonSize, JsonDeserializationErrors *errors =
nullptr)
1098 if (!doc.IsString()) {
1105 return doc.GetString();
1111 template <
typename Type, Traits::EnableIf<IsArray<Type>> * =
nullptr>
1112 Type
fromJson(
const char *json, std::size_t jsonSize, JsonDeserializationErrors *errors =
nullptr)
1115 if (!doc.IsArray()) {
1123 pull<Type>(res, doc.GetArray(), errors);
1132 return fromJson<Type>(json, std::strlen(json), errors);
1140 return fromJson<Type>(json.data(), json.size(), errors);
1146 #endif // REFLECTIVE_RAPIDJSON_JSON_REFLECTOR_H