Add experimental support for multimap
Makes sense for binary (de)serialization, not sure about JSON (de)serialization
This commit is contained in:
parent
f77229471a
commit
d64174c000
|
@ -82,7 +82,9 @@ The following table shows the mapping of supported C++ types to supported JSON t
|
||||||
* custom types must provide a default constructor.
|
* custom types must provide a default constructor.
|
||||||
* constant member variables are skipped.
|
* constant member variables are skipped.
|
||||||
* It is possible to treat custom types as set/map using the macro `REFLECTIVE_RAPIDJSON_TREAT_AS_MAP_OR_HASH`,
|
* It is possible to treat custom types as set/map using the macro `REFLECTIVE_RAPIDJSON_TREAT_AS_MAP_OR_HASH`,
|
||||||
`REFLECTIVE_RAPIDJSON_TREAT_AS_SET` or `REFLECTIVE_RAPIDJSON_TREAT_AS_MULTI_SET`.
|
`REFLECTIVE_RAPIDJSON_TREAT_AS_MULTI_MAP_OR_HASH`, `REFLECTIVE_RAPIDJSON_TREAT_AS_SET` or
|
||||||
|
`REFLECTIVE_RAPIDJSON_TREAT_AS_MULTI_SET`.
|
||||||
|
* The key type of the `std::map`, `std::unordered_map` must be `std::string`.
|
||||||
* For custom (de)serialization, see the section below.
|
* For custom (de)serialization, see the section below.
|
||||||
* The binary (de)serializer supports approximately the same C++ types but obviously maps them to a platform
|
* The binary (de)serializer supports approximately the same C++ types but obviously maps them to a platform
|
||||||
independent binary representation rather than a JSON type.
|
independent binary representation rather than a JSON type.
|
||||||
|
|
|
@ -58,10 +58,10 @@ public:
|
||||||
template <typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::unique_ptr>> * = nullptr> void read(Type &pair);
|
template <typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::unique_ptr>> * = nullptr> void read(Type &pair);
|
||||||
template <typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::shared_ptr>> * = nullptr> void read(Type &pair);
|
template <typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::shared_ptr>> * = nullptr> void read(Type &pair);
|
||||||
template <typename Type, Traits::EnableIf<IsArray<Type>, Traits::IsResizable<Type>> * = nullptr> void read(Type &iteratable);
|
template <typename Type, Traits::EnableIf<IsArray<Type>, Traits::IsResizable<Type>> * = nullptr> void read(Type &iteratable);
|
||||||
template <typename Type, Traits::EnableIf<IsMapOrHash<Type>> * = nullptr> void read(Type &iteratable);
|
template <typename Type, Traits::EnableIfAny<IsMapOrHash<Type>, IsMultiMapOrHash<Type>> * = nullptr> void read(Type &iteratable);
|
||||||
template <typename Type,
|
template <typename Type,
|
||||||
Traits::EnableIf<IsIteratableExceptString<Type>, Traits::None<IsMapOrHash<Type>, Traits::All<IsArray<Type>, Traits::IsResizable<Type>>>>
|
Traits::EnableIf<IsIteratableExceptString<Type>,
|
||||||
* = nullptr>
|
Traits::None<IsMapOrHash<Type>, IsMultiMapOrHash<Type>, Traits::All<IsArray<Type>, Traits::IsResizable<Type>>>> * = nullptr>
|
||||||
void read(Type &iteratable);
|
void read(Type &iteratable);
|
||||||
template <typename Type, Traits::EnableIf<std::is_enum<Type>> * = nullptr> void read(Type &customType);
|
template <typename Type, Traits::EnableIf<std::is_enum<Type>> * = nullptr> void read(Type &customType);
|
||||||
template <typename Type, Traits::EnableIf<IsCustomType<Type>> * = nullptr> void read(Type &customType);
|
template <typename Type, Traits::EnableIf<IsCustomType<Type>> * = nullptr> void read(Type &customType);
|
||||||
|
@ -138,7 +138,7 @@ template <typename Type, Traits::EnableIf<IsArray<Type>, Traits::IsResizable<Typ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type, Traits::EnableIf<IsMapOrHash<Type>> *> void BinaryDeserializer::read(Type &iteratable)
|
template <typename Type, Traits::EnableIfAny<IsMapOrHash<Type>, IsMultiMapOrHash<Type>> *> void BinaryDeserializer::read(Type &iteratable)
|
||||||
{
|
{
|
||||||
const auto size = readVariableLengthUIntBE();
|
const auto size = readVariableLengthUIntBE();
|
||||||
for (size_t i = 0; i != size; ++i) {
|
for (size_t i = 0; i != size; ++i) {
|
||||||
|
@ -149,7 +149,8 @@ template <typename Type, Traits::EnableIf<IsMapOrHash<Type>> *> void BinaryDeser
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type,
|
template <typename Type,
|
||||||
Traits::EnableIf<IsIteratableExceptString<Type>, Traits::None<IsMapOrHash<Type>, Traits::All<IsArray<Type>, Traits::IsResizable<Type>>>> *>
|
Traits::EnableIf<IsIteratableExceptString<Type>,
|
||||||
|
Traits::None<IsMapOrHash<Type>, IsMultiMapOrHash<Type>, Traits::All<IsArray<Type>, Traits::IsResizable<Type>>>> *>
|
||||||
void BinaryDeserializer::read(Type &iteratable)
|
void BinaryDeserializer::read(Type &iteratable)
|
||||||
{
|
{
|
||||||
const auto size = readVariableLengthUIntBE();
|
const auto size = readVariableLengthUIntBE();
|
||||||
|
|
|
@ -211,9 +211,10 @@ void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Pushes the specified map (std::map, std::unordered_map) to the specified value.
|
* \brief Pushes the specified map (std::map, std::unordered_map) or multimap (std::multimap, std::unordered_multimap) to the
|
||||||
|
* specified value.
|
||||||
*/
|
*/
|
||||||
template <typename Type, Traits::EnableIf<IsMapOrHash<Type>> * = nullptr>
|
template <typename Type, Traits::EnableIfAny<IsMapOrHash<Type>, IsMultiMapOrHash<Type>> * = nullptr>
|
||||||
void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
|
void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
|
||||||
{
|
{
|
||||||
value.SetObject();
|
value.SetObject();
|
||||||
|
@ -371,6 +372,12 @@ void pull(Type &reflectable, rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<c
|
||||||
template <typename Type, Traits::EnableIf<IsMapOrHash<Type>> * = nullptr>
|
template <typename Type, Traits::EnableIf<IsMapOrHash<Type>> * = nullptr>
|
||||||
void pull(Type &reflectable, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
|
void pull(Type &reflectable, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Pulls the specified \a reflectable which is a multimap from the specified value which is checked to contain an object.
|
||||||
|
*/
|
||||||
|
template <typename Type, Traits::EnableIf<IsMultiMapOrHash<Type>> * = nullptr>
|
||||||
|
void pull(Type &reflectable, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Pulls the specified \a reflectable which is a tuple from the specified value which is checked to contain an array.
|
* \brief Pulls the specified \a reflectable which is a tuple from the specified value which is checked to contain an array.
|
||||||
*/
|
*/
|
||||||
|
@ -628,6 +635,25 @@ void pull(Type &reflectable, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Pulls the specified \a reflectable which is a multimap from the specified value which is checked to contain an object.
|
||||||
|
*/
|
||||||
|
template <typename Type, Traits::EnableIf<IsMultiMapOrHash<Type>> *>
|
||||||
|
void pull(Type &reflectable, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
|
||||||
|
{
|
||||||
|
if (!value.IsObject()) {
|
||||||
|
if (errors) {
|
||||||
|
errors->reportTypeMismatch<Type>(value.GetType());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto obj = value.GetObject();
|
||||||
|
for (auto i = obj.MemberBegin(), end = obj.MemberEnd(); i != end; ++i) {
|
||||||
|
auto insertedIterator = reflectable.insert(typename Type::value_type(i->name.GetString(), typename Type::mapped_type()));
|
||||||
|
pull(insertedIterator->second, i->value, errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace Detail {
|
namespace Detail {
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -762,7 +788,7 @@ void pull(Type &reflectable, const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_N
|
||||||
/*!
|
/*!
|
||||||
* \brief Serializes the specified \a reflectable which has a custom type or can be mapped to and object.
|
* \brief Serializes the specified \a reflectable which has a custom type or can be mapped to and object.
|
||||||
*/
|
*/
|
||||||
template <typename Type, Traits::EnableIfAny<IsJsonSerializable<Type>, IsMapOrHash<Type>> * = nullptr>
|
template <typename Type, Traits::EnableIfAny<IsJsonSerializable<Type>, IsMapOrHash<Type>, IsMultiMapOrHash<Type>> * = nullptr>
|
||||||
RAPIDJSON_NAMESPACE::StringBuffer toJson(const Type &reflectable)
|
RAPIDJSON_NAMESPACE::StringBuffer toJson(const Type &reflectable)
|
||||||
{
|
{
|
||||||
RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kObjectType);
|
RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kObjectType);
|
||||||
|
@ -819,7 +845,7 @@ template <typename Type, Traits::EnableIf<IsArray<Type>> * = nullptr> RAPIDJSON_
|
||||||
/*!
|
/*!
|
||||||
* \brief Deserializes the specified JSON to \tparam Type which is a custom type or can be mapped to an object.
|
* \brief Deserializes the specified JSON to \tparam Type which is a custom type or can be mapped to an object.
|
||||||
*/
|
*/
|
||||||
template <typename Type, Traits::EnableIfAny<IsJsonSerializable<Type>, IsMapOrHash<Type>> * = nullptr>
|
template <typename Type, Traits::EnableIfAny<IsJsonSerializable<Type>, IsMapOrHash<Type>, IsMultiMapOrHash<Type>> * = nullptr>
|
||||||
Type fromJson(const char *json, std::size_t jsonSize, JsonDeserializationErrors *errors = nullptr)
|
Type fromJson(const char *json, std::size_t jsonSize, JsonDeserializationErrors *errors = nullptr)
|
||||||
{
|
{
|
||||||
RAPIDJSON_NAMESPACE::Document doc(parseJsonDocFromString(json, jsonSize));
|
RAPIDJSON_NAMESPACE::Document doc(parseJsonDocFromString(json, jsonSize));
|
||||||
|
|
|
@ -12,6 +12,7 @@ struct Foo {
|
||||||
struct Bar {
|
struct Bar {
|
||||||
};
|
};
|
||||||
REFLECTIVE_RAPIDJSON_TREAT_AS_MAP_OR_HASH(Foo);
|
REFLECTIVE_RAPIDJSON_TREAT_AS_MAP_OR_HASH(Foo);
|
||||||
|
REFLECTIVE_RAPIDJSON_TREAT_AS_MULTI_MAP_OR_HASH(Foo);
|
||||||
REFLECTIVE_RAPIDJSON_TREAT_AS_SET(Bar);
|
REFLECTIVE_RAPIDJSON_TREAT_AS_SET(Bar);
|
||||||
REFLECTIVE_RAPIDJSON_TREAT_AS_MULTI_SET(Foo);
|
REFLECTIVE_RAPIDJSON_TREAT_AS_MULTI_SET(Foo);
|
||||||
|
|
||||||
|
@ -37,6 +38,10 @@ static_assert(IsMapOrHash<map<string, int>>::value, "map mapped to object");
|
||||||
static_assert(IsMapOrHash<unordered_map<string, int>>::value, "hash mapped to object");
|
static_assert(IsMapOrHash<unordered_map<string, int>>::value, "hash mapped to object");
|
||||||
static_assert(!IsMapOrHash<vector<int>>::value, "vector not mapped to object");
|
static_assert(!IsMapOrHash<vector<int>>::value, "vector not mapped to object");
|
||||||
static_assert(IsMapOrHash<Foo>::value, "Foo mapped to object via TreatAsMapOrHash");
|
static_assert(IsMapOrHash<Foo>::value, "Foo mapped to object via TreatAsMapOrHash");
|
||||||
|
static_assert(IsMultiMapOrHash<multimap<string, int>>::value, "multimap mapped to object");
|
||||||
|
static_assert(IsMultiMapOrHash<unordered_multimap<string, int>>::value, "unordered multimap mapped to object");
|
||||||
|
static_assert(!IsMultiMapOrHash<vector<int>>::value, "vector not mapped to object");
|
||||||
|
static_assert(IsMultiMapOrHash<Foo>::value, "Foo mapped to object via TreatAsMultiMapOrHash");
|
||||||
static_assert(IsIteratableExceptString<std::vector<int>>::value, "vector is iteratable");
|
static_assert(IsIteratableExceptString<std::vector<int>>::value, "vector is iteratable");
|
||||||
static_assert(!IsIteratableExceptString<std::string>::value, "string not iteratable");
|
static_assert(!IsIteratableExceptString<std::string>::value, "string not iteratable");
|
||||||
static_assert(!IsIteratableExceptString<std::wstring>::value, "wstring not iteratable");
|
static_assert(!IsIteratableExceptString<std::wstring>::value, "wstring not iteratable");
|
||||||
|
|
|
@ -15,6 +15,9 @@ namespace ReflectiveRapidJSON {
|
||||||
/// \brief \brief The TreatAsMapOrHash class allows treating custom classes as std::map or std::unordered_map.
|
/// \brief \brief The TreatAsMapOrHash class allows treating custom classes as std::map or std::unordered_map.
|
||||||
template <typename T> struct TreatAsMapOrHash : public Traits::Bool<false> {
|
template <typename T> struct TreatAsMapOrHash : public Traits::Bool<false> {
|
||||||
};
|
};
|
||||||
|
/// \brief \brief The TreatAsMultiMapOrHash class allows treating custom classes as std::multimap or std::unordered_multimap.
|
||||||
|
template <typename T> struct TreatAsMultiMapOrHash : public Traits::Bool<false> {
|
||||||
|
};
|
||||||
/// \brief \brief The TreatAsSet class allows treating custom classes as std::set or std::unordered_set.
|
/// \brief \brief The TreatAsSet class allows treating custom classes as std::set or std::unordered_set.
|
||||||
template <typename T> struct TreatAsSet : public Traits::Bool<false> {
|
template <typename T> struct TreatAsSet : public Traits::Bool<false> {
|
||||||
};
|
};
|
||||||
|
@ -25,6 +28,9 @@ template <typename T> struct TreatAsMultiSet : public Traits::Bool<false> {
|
||||||
#define REFLECTIVE_RAPIDJSON_TREAT_AS_MAP_OR_HASH(T) \
|
#define REFLECTIVE_RAPIDJSON_TREAT_AS_MAP_OR_HASH(T) \
|
||||||
template <> struct TreatAsMapOrHash<T> : public Traits::Bool<true> { \
|
template <> struct TreatAsMapOrHash<T> : public Traits::Bool<true> { \
|
||||||
}
|
}
|
||||||
|
#define REFLECTIVE_RAPIDJSON_TREAT_AS_MULTI_MAP_OR_HASH(T) \
|
||||||
|
template <> struct TreatAsMultiMapOrHash<T> : public Traits::Bool<true> { \
|
||||||
|
}
|
||||||
#define REFLECTIVE_RAPIDJSON_TREAT_AS_SET(T) \
|
#define REFLECTIVE_RAPIDJSON_TREAT_AS_SET(T) \
|
||||||
template <> struct TreatAsSet<T> : public Traits::Bool<true> { \
|
template <> struct TreatAsSet<T> : public Traits::Bool<true> { \
|
||||||
}
|
}
|
||||||
|
@ -37,6 +43,9 @@ template <typename Type>
|
||||||
using IsMapOrHash
|
using IsMapOrHash
|
||||||
= Traits::Any<Traits::IsSpecializationOf<Type, std::map>, Traits::IsSpecializationOf<Type, std::unordered_map>, TreatAsMapOrHash<Type>>;
|
= Traits::Any<Traits::IsSpecializationOf<Type, std::map>, Traits::IsSpecializationOf<Type, std::unordered_map>, TreatAsMapOrHash<Type>>;
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
|
using IsMultiMapOrHash = Traits::Any<Traits::IsSpecializationOf<Type, std::multimap>, Traits::IsSpecializationOf<Type, std::unordered_multimap>,
|
||||||
|
TreatAsMultiMapOrHash<Type>>;
|
||||||
|
template <typename Type>
|
||||||
using IsSet = Traits::Any<Traits::IsSpecializationOf<Type, std::set>, Traits::IsSpecializationOf<Type, std::unordered_set>, TreatAsSet<Type>>;
|
using IsSet = Traits::Any<Traits::IsSpecializationOf<Type, std::set>, Traits::IsSpecializationOf<Type, std::unordered_set>, TreatAsSet<Type>>;
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
using IsMultiSet
|
using IsMultiSet
|
||||||
|
|
Loading…
Reference in New Issue