diff --git a/README.md b/README.md index 637d53c..7c50e43 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ The following table shows the mapping of supported C++ types to supported JSON t | `const char *` | string | | iteratable lists (`std::vector`, `std::list`, ...) | array | | sets (`std::set`, `std::unordered_set`, `std::multiset`, ...) | array | -| `std::tuple` | array | +| `std::pair`, `std::tuple` | array | | `std::unique_ptr`, `std::shared_ptr` | depends/null | | `std::map`, `std::unordered_map`, `std::multimap`, `std::unordered_multimap` | object | | `std::variant` | object | diff --git a/lib/json/reflector.h b/lib/json/reflector.h index e972767..8b21452 100644 --- a/lib/json/reflector.h +++ b/lib/json/reflector.h @@ -81,8 +81,9 @@ inline RAPIDJSON_NAMESPACE::Document parseJsonDocFromString(const char *json, st // define traits to distinguish between "built-in" types like int, std::string, std::vector, ... and custom structs/classes template using IsBuiltInType = Traits::Any, std::is_floating_point, std::is_pointer, std::is_enum, - Traits::IsSpecializationOf, Traits::IsIteratable, Traits::IsSpecializationOf, - Traits::IsSpecializationOf, Traits::IsSpecializationOf, IsVariant>; + Traits::IsSpecializationOf, Traits::IsSpecializationOf, Traits::IsIteratable, + Traits::IsSpecializationOf, Traits::IsSpecializationOf, + Traits::IsSpecializationOf, IsVariant>; template using IsCustomType = Traits::Not>; // define trait to check for custom structs/classes which are JSON serializable @@ -237,16 +238,16 @@ void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_ { value.SetObject(); for (const auto &item : reflectable) { - auto arrayValue = RAPIDJSON_NAMESPACE::Value(RAPIDJSON_NAMESPACE::Type::kArrayType); const auto memberName = RAPIDJSON_NAMESPACE::Value::StringRefType(item.first.data(), rapidJsonSize(item.first.size())); const auto existingMember = value.FindMember(memberName); - if (existingMember != value.MemberEnd() && existingMember->value.GetType() == RAPIDJSON_NAMESPACE::Type::kArrayType) { - arrayValue = existingMember->value; - } else { - value.AddMember(memberName, arrayValue, allocator); - } - RAPIDJSON_NAMESPACE::Value::Array array = arrayValue.GetArray(); + const auto arrayAlreadyExists + = existingMember != value.MemberEnd() && existingMember->value.GetType() == RAPIDJSON_NAMESPACE::Type::kArrayType; + auto newArrayValue = RAPIDJSON_NAMESPACE::Value{ RAPIDJSON_NAMESPACE::kArrayType }; + RAPIDJSON_NAMESPACE::Value::Array array = arrayAlreadyExists ? existingMember->value.GetArray() : newArrayValue.GetArray(); push(item.second, array, allocator); + if (!arrayAlreadyExists) { + value.AddMember(memberName, newArrayValue, allocator); + } } } @@ -283,6 +284,19 @@ void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_ Detail::TuplePushHelper::value>::push(reflectable, array, allocator); } +/*! + * \brief Pushes the specified pair to the specified value. + */ +template > * = nullptr> +void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator) +{ + value.SetArray(); + RAPIDJSON_NAMESPACE::Value::Array array(value.GetArray()); + array.Reserve(2, allocator); + push(reflectable.first, array, allocator); + push(reflectable.second, array, allocator); +} + /*! * \brief Pushes the specified unique_ptr, shared_ptr or weak_ptr to the specified value. */ @@ -439,6 +453,12 @@ void pull(Type &reflectable, const rapidjson::GenericValue> * = nullptr> void pull(Type &reflectable, const rapidjson::GenericValue> &value, JsonDeserializationErrors *errors); +/*! + * \brief Pulls the specified \a reflectable which is a pair from the specified value which is checked to contain an array. + */ +template > * = nullptr> +void pull(Type &reflectable, const rapidjson::GenericValue> &value, JsonDeserializationErrors *errors); + /*! * \brief Pulls the specified \a reflectable which is a unique_ptr from the specified value which might be null. */ @@ -757,7 +777,7 @@ void pull(Type &reflectable, const rapidjson::GenericValue::value) { if (errors) { // FIXME: report expected and actual size @@ -768,6 +788,30 @@ void pull(Type &reflectable, const rapidjson::GenericValue::value>::pull(reflectable, array, errors); } +/*! + * \brief Pulls the specified \a reflectable which is a pair from the specified value which is checked to contain an array. + */ +template > *> +void pull(Type &reflectable, const rapidjson::GenericValue> &value, JsonDeserializationErrors *errors) +{ + if (!value.IsArray()) { + if (errors) { + errors->reportTypeMismatch(value.GetType()); + } + return; + } + const auto array = value.GetArray(); + if (array.Size() != 2) { + if (errors) { + // FIXME: report expected and actual size + errors->reportArraySizeMismatch(); + } + return; + } + pull(reflectable.first, array[0], errors); + pull(reflectable.second, array[1], errors); +} + /*! * \brief Pulls the specified \a reflectable which is a unique_ptr from the specified value which might be null. */