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::EnableIf<std::is_same<Type, const
char *>> * =
nullptr>
170 inline void push(Type reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
172 value.SetString(RAPIDJSON_NAMESPACE::StringRef(reflectable), allocator);
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)
181 value.SetString(RAPIDJSON_NAMESPACE::StringRef(reflectable), allocator);
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)
190 value.SetString(RAPIDJSON_NAMESPACE::StringRef(reflectable.data(), reflectable.size()), allocator);
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)
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);
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)
214 RAPIDJSON_NAMESPACE::Value::Array array(value.GetArray());
215 for (
const auto &item : reflectable) {
216 push(item, array, allocator);
223 template <
typename Type, Traits::EnableIfAny<IsMapOrHash<Type>> * =
nullptr>
224 void push(
const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
227 RAPIDJSON_NAMESPACE::Value::Object object(value.GetObject());
228 for (
const auto &item : reflectable) {
229 push(item.second, item.first.data(),
object, allocator);
236 template <
typename Type, Traits::EnableIfAny<IsMultiMapOrHash<Type>> * =
nullptr>
237 void push(
const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
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);
260 static void push(
const Tuple &tuple, RAPIDJSON_NAMESPACE::Value::Array &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
268 static void push(
const Tuple &tuple, RAPIDJSON_NAMESPACE::Value::Array &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
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)
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);
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)
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);
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)
312 push(*reflectable, value, allocator);
318 template <
typename Type, Traits::EnableIf<IsVariant<Type>> * =
nullptr>
319 void push(
const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
321 if (reflectable.valueless_by_exception()) {
326 RAPIDJSON_NAMESPACE::Value index, data;
327 index.SetInt(reflectable.index());
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);
333 CPP_UTILITIES_UNUSED(data)
334 CPP_UTILITIES_UNUSED(allocator)
340 value.AddMember(
"index", index, allocator);
341 value.AddMember(
"data", data, allocator);
347 template <
typename Type, Traits::EnableIf<IsJsonSerializable<Type>> *>
348 void push(
const Type &reflectable, RAPIDJSON_NAMESPACE::Value::Array &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
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);
359 template <
typename Type, Traits::DisableIf<IsJsonSerializable<Type>> *>
360 void push(
const Type &reflectable, RAPIDJSON_NAMESPACE::Value::Array &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
362 RAPIDJSON_NAMESPACE::Value genericValue;
363 push(reflectable, genericValue, allocator);
364 value.PushBack(genericValue, allocator);
370 template <
typename Type, Traits::EnableIf<IsJsonSerializable<Type>> *>
372 const Type &reflectable,
const char *name, RAPIDJSON_NAMESPACE::Value::Object &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
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);
383 template <
typename Type, Traits::DisableIf<IsJsonSerializable<Type>> *>
385 const Type &reflectable,
const char *name, RAPIDJSON_NAMESPACE::Value::Object &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
387 RAPIDJSON_NAMESPACE::Value genericValue;
388 push(reflectable, genericValue, allocator);
389 value.AddMember(RAPIDJSON_NAMESPACE::StringRef(name), genericValue, allocator);
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);
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);
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);
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);
423 template <
typename Type, Traits::EnableIf<IsArray<Type>> * =
nullptr>
424 void pull(Type &reflectable, rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>>::ConstArray array, JsonDeserializationErrors *errors);
429 template <
typename Type, Traits::EnableIf<IsSet<Type>> * =
nullptr>
430 void pull(Type &reflectable, rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>>::ConstArray array, JsonDeserializationErrors *errors);
435 template <
typename Type, Traits::EnableIf<IsMultiSet<Type>> * =
nullptr>
436 void pull(Type &reflectable, rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>>::ConstArray array, JsonDeserializationErrors *errors);
441 template <
typename Type, Traits::EnableIf<IsMapOrHash<Type>> * =
nullptr>
442 void pull(Type &reflectable,
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
447 template <
typename Type, Traits::EnableIf<IsMultiMapOrHash<Type>> * =
nullptr>
448 void pull(Type &reflectable,
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
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);
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);
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);
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);
477 template <
typename Type, Traits::EnableIf<IsVariant<Type>> * =
nullptr>
478 void pull(Type &reflectable,
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
483 template <
typename Type>
485 Type &reflectable, rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>>::ValueIterator &value, JsonDeserializationErrors *errors);
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);
499 template <
typename Type, Traits::DisableIf<IsBuiltInType<Type>> *>
500 void pull(Type &reflectable,
const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
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>
508 Type &reflectable,
const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value,
JsonDeserializationErrors *errors)
510 if (!value.IsNumber()) {
516 reflectable = value.Is<Type>() ? value.Get<Type>() :
static_cast<Type
>(value.GetDouble());
522 template <
typename Type, Traits::EnableIf<std::is_same<Type,
bool>> * =
nullptr>
524 Type &reflectable,
const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value,
JsonDeserializationErrors *errors)
526 if (!value.IsBool()) {
532 reflectable = value.GetBool();
539 template <
typename Type, Traits::EnableIfAny<std::is_enum<Type>> * =
nullptr>
541 Type &reflectable,
const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
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>()) {
546 errors->reportTypeMismatch<ExpectedType>(value.GetType());
550 reflectable =
static_cast<Type
>(value.Get<ExpectedType>());
556 template <
typename Type, Traits::EnableIf<std::is_same<Type, std::
string>> * =
nullptr>
558 Type &reflectable,
const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
560 if (!value.IsString()) {
562 errors->reportTypeMismatch<std::string>(value.GetType());
566 reflectable = value.GetString();
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)
576 if (!value.IsString()) {
578 errors->reportTypeMismatch<std::string>(value.GetType());
587 template <
typename Type, Traits::EnableIf<IsArrayOrSet<Type>, Traits::Not<Traits::IsReservable<Type>>> *>
590 if (!value.IsArray()) {
596 pull(reflectable, value.GetArray(), errors);
602 template <
typename Type, Traits::EnableIf<IsArrayOrSet<Type>, Traits::IsReservable<Type>> *>
605 if (!value.IsArray()) {
611 auto array = value.GetArray();
612 reflectable.reserve(array.Size());
613 pull(reflectable, array, errors);
619 template <
typename Type, Traits::EnableIf<IsArray<Type>> *>
626 std::size_t index = 0;
627 for (
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &item : array) {
633 reflectable.emplace_back();
634 pull(reflectable.back(), item, errors);
646 template <
typename Type, Traits::EnableIf<IsMultiSet<Type>> *>
653 std::size_t index = 0;
654 for (
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &item : array) {
660 typename Type::value_type itemObj;
661 pull(itemObj, item, errors);
662 reflectable.emplace(move(itemObj));
674 template <
typename Type, Traits::EnableIf<IsSet<Type>> *>
675 void pull(Type &reflectable, rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>>::ConstArray array, JsonDeserializationErrors *errors)
681 std::size_t index = 0;
682 for (
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &item : array) {
685 errors->currentIndex = index;
688 typename Type::value_type itemObj;
689 pull(itemObj, item, errors);
690 if (!reflectable.emplace(move(itemObj)).second) {
704 template <
typename Type, Traits::EnableIf<IsMapOrHash<Type>> *>
705 void pull(Type &reflectable,
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
707 if (!value.IsObject()) {
709 errors->reportTypeMismatch<Type>(value.GetType());
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);
722 template <
typename Type, Traits::EnableIf<IsMultiMapOrHash<Type>> *>
723 void pull(Type &reflectable,
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
725 if (!value.IsObject()) {
727 errors->reportTypeMismatch<Type>(value.GetType());
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);
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);
756 JsonReflector::pull<
typename std::tuple_element<N - 1, Tuple>::type>(std::get<N - 1>(tuple), value[N - 1], errors);
763 JsonReflector::pull<typename std::tuple_element<0, Tuple>::type>(std::get<0>(tuple), value[0], errors);
771 template <
typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::tuple>> *>
774 if (!value.IsArray()) {
780 const auto array = value.GetArray();
781 if (array.Size() != std::tuple_size<Type>::value) {
788 Detail::TuplePullHelper<Type, std::tuple_size<Type>::value>
::pull(reflectable, array, errors);
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)
797 if (!value.IsArray()) {
799 errors->reportTypeMismatch<Type>(value.GetType());
803 const auto array = value.GetArray();
804 if (array.Size() != 2) {
807 errors->reportArraySizeMismatch();
811 pull(reflectable.first, array[0], errors);
812 pull(reflectable.second, array[1], errors);
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)
821 if (value.IsNull()) {
825 reflectable = std::make_unique<typename Type::element_type>();
826 pull(*reflectable, value, errors);
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)
835 if (value.IsNull()) {
839 reflectable = std::make_shared<typename Type::element_type>();
840 pull(*reflectable, value, errors);
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)
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{};
854 pull(variant.template emplace<compiletimeIndex>(), value, errors);
857 assignVariantValueByRuntimeIndex<Variant, compiletimeIndex + 1>(runtimeIndex, variant, value, errors);
862 errors->currentMember, errors->currentIndex);
872 template <
typename Type, Traits::EnableIf<IsVariant<Type>> *>
873 void pull(Type &reflectable,
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
875 if (!value.IsObject()) {
877 errors->reportTypeMismatch<Type>(value.GetType());
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()) {
888 errors->currentMember, errors->currentIndex);
892 const auto &indexValue = indexIterator->value;
893 if (!indexValue.IsInt()) {
896 errors->currentRecord, errors->currentMember, errors->currentIndex);
900 const auto index = indexValue.GetInt();
903 errors->currentMember, errors->currentIndex);
906 Detail::assignVariantValueByRuntimeIndex(
static_cast<std::size_t
>(index), reflectable, dataIterator->value, errors);
912 template <
typename Type>
915 pull<Type>(reflectable, *value, errors);
924 template <
typename Type>
925 inline void pull(Type &reflectable,
const char *name,
const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>>::ConstObject &value,
929 const auto member = value.FindMember(name);
930 if (member == value.MemberEnd()) {
935 const char *previousMember;
942 pull<Type>(reflectable, member->value, errors);
953 template <
typename Type, Traits::DisableIf<IsBuiltInType<Type>> *>
954 void pull(Type &reflectable,
const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value,
JsonDeserializationErrors *errors)
956 if (!value.IsObject()) {
962 pull(reflectable, value.GetObject(), errors);
970 template <
typename Type, Traits::EnableIfAny<IsJsonSerializable<Type>, IsMapOrHash<Type>, IsMultiMapOrHash<Type>> * =
nullptr>
973 RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kObjectType);
974 push(reflectable, document, document.GetAllocator());
981 template <
typename Type, Traits::EnableIfAny<std::is_
integral<Type>, std::is_
floating_po
int<Type>> * =
nullptr>
984 RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kNumberType);
985 document.Set(reflectable, document.GetAllocator());
992 template <
typename Type, Traits::EnableIf<std::is_same<Type, std::
string>> * =
nullptr>
995 RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kStringType);
996 document.SetString(RAPIDJSON_NAMESPACE::StringRef(reflectable.data(), reflectable.size()), document.GetAllocator());
1003 template <
typename Type, Traits::EnableIf<std::is_same<Type, const
char *>> * =
nullptr>
1006 RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kStringType);
1007 document.SetString(RAPIDJSON_NAMESPACE::StringRef(reflectable), document.GetAllocator());
1014 template <
typename Type, Traits::EnableIf<IsArray<Type>> * =
nullptr> RAPIDJSON_NAMESPACE::Document
toJsonDocument(
const Type &reflectable)
1016 RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kArrayType);
1017 push(reflectable, document, document.GetAllocator());
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)
1038 template <
typename Type, Traits::EnableIfAny<IsJsonSerializable<Type>, IsMapOrHash<Type>, IsMultiMapOrHash<Type>> * =
nullptr>
1042 if (!doc.IsObject()) {
1050 pull<Type>(res, doc.GetObject(), errors);
1057 template <
typename Type, Traits::EnableIfAny<std::is_
integral<Type>, std::is_
floating_po
int<Type>> * =
nullptr>
1061 if (!doc.Is<Type>()) {
1068 return doc.Get<Type>();
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)
1078 if (!doc.IsString()) {
1085 return doc.GetString();
1091 template <
typename Type, Traits::EnableIf<IsArray<Type>> * =
nullptr>
1092 Type
fromJson(
const char *json, std::size_t jsonSize, JsonDeserializationErrors *errors =
nullptr)
1095 if (!doc.IsArray()) {
1103 pull<Type>(res, doc.GetArray(), errors);
1112 return fromJson<Type>(json, std::strlen(json), errors);
1120 return fromJson<Type>(json.data(), json.size(), errors);
1126 #endif // REFLECTIVE_RAPIDJSON_JSON_REFLECTOR_H