Fix incomplete use of AdaptedJsonSerializable and handling tuple
This commit is contained in:
parent
4655387c4d
commit
e9324f0ec3
|
@ -220,21 +220,41 @@ void JsonGeneratorTests::testCustomSerialization()
|
|||
*/
|
||||
void JsonGeneratorTests::test3rdPartyAdaption()
|
||||
{
|
||||
// test whether specializations of AdaptedJsonSerializable are generated
|
||||
static_assert(
|
||||
ReflectiveRapidJSON::AdaptedJsonSerializable<NotJsonSerializable>::value, "can serialize NotJsonSerializable because of adaption macro");
|
||||
static_assert(ReflectiveRapidJSON::AdaptedJsonSerializable<NestedNotJsonSerializable>::value,
|
||||
"can serialize NestedNotJsonSerializable because of adaption macro");
|
||||
static_assert(!ReflectiveRapidJSON::AdaptedJsonSerializable<OtherNotJsonSerializable>::value,
|
||||
"can not serialize OtherNotJsonSerializable because adaption macro missing");
|
||||
static_assert(!ReflectiveRapidJSON::AdaptedJsonSerializable<ReallyNotJsonSerializable>::value, "can not serialize ReallyNotJsonSerializable");
|
||||
|
||||
const NotJsonSerializable test;
|
||||
const string str("{\"butSerializableAnyways\":\"useful to adapt 3rd party structs\"}");
|
||||
const NotJsonSerializable simple;
|
||||
const string strSimple("{\"butSerializableAnyways\":\"useful to adapt 3rd party structs\"}");
|
||||
const NestedNotJsonSerializable nested{ { "foo" }, { { "1" }, { "2" }, { "3" } }, { 42, { "bar" } } };
|
||||
const string strNested("{\"asMember\":{\"butSerializableAnyways\":\"foo\"},\"asArrayElement\":[{\"butSerializableAnyways\":\"1\"},{"
|
||||
"\"butSerializableAnyways\":\"2\"},{\"butSerializableAnyways\":\"3\"}],\"asTupleElement\":[42,{\"butSerializableAnyways\":"
|
||||
"\"bar\"}]}");
|
||||
|
||||
// test serialization
|
||||
CPPUNIT_ASSERT_EQUAL(str, string(ReflectiveRapidJSON::JsonReflector::toJson(test).GetString()));
|
||||
CPPUNIT_ASSERT_EQUAL(strSimple, string(ReflectiveRapidJSON::JsonReflector::toJson(simple).GetString()));
|
||||
CPPUNIT_ASSERT_EQUAL(strNested, string(ReflectiveRapidJSON::JsonReflector::toJson(nested).GetString()));
|
||||
|
||||
// test deserialization
|
||||
const NotJsonSerializable parsedTest(ReflectiveRapidJSON::JsonReflector::fromJson<NotJsonSerializable>(str));
|
||||
CPPUNIT_ASSERT_EQUAL(test.butSerializableAnyways, parsedTest.butSerializableAnyways);
|
||||
JsonDeserializationErrors errors;
|
||||
const auto parsedSimple(ReflectiveRapidJSON::JsonReflector::fromJson<NotJsonSerializable>(strSimple, &errors));
|
||||
CPPUNIT_ASSERT_EQUAL(0_st, errors.size());
|
||||
CPPUNIT_ASSERT_EQUAL(simple.butSerializableAnyways, parsedSimple.butSerializableAnyways);
|
||||
const auto parsedNested(ReflectiveRapidJSON::JsonReflector::fromJson<NestedNotJsonSerializable>(strNested, &errors));
|
||||
CPPUNIT_ASSERT_EQUAL(0_st, errors.size());
|
||||
CPPUNIT_ASSERT_EQUAL(nested.asMember.butSerializableAnyways, parsedNested.asMember.butSerializableAnyways);
|
||||
CPPUNIT_ASSERT_EQUAL(nested.asMember.butSerializableAnyways, parsedNested.asMember.butSerializableAnyways);
|
||||
CPPUNIT_ASSERT_EQUAL(nested.asArrayElement.size(), parsedNested.asArrayElement.size());
|
||||
CPPUNIT_ASSERT_EQUAL(nested.asArrayElement.at(0).butSerializableAnyways, parsedNested.asArrayElement.at(0).butSerializableAnyways);
|
||||
CPPUNIT_ASSERT_EQUAL(nested.asArrayElement.at(1).butSerializableAnyways, parsedNested.asArrayElement.at(1).butSerializableAnyways);
|
||||
CPPUNIT_ASSERT_EQUAL(nested.asArrayElement.at(2).butSerializableAnyways, parsedNested.asArrayElement.at(2).butSerializableAnyways);
|
||||
CPPUNIT_ASSERT_EQUAL(get<0>(nested.asTupleElement), get<0>(parsedNested.asTupleElement));
|
||||
CPPUNIT_ASSERT_EQUAL(get<1>(nested.asTupleElement).butSerializableAnyways, get<1>(parsedNested.asTupleElement).butSerializableAnyways);
|
||||
}
|
||||
|
||||
// include file required for reflection of TestStruct and other structs defined in structs.h
|
||||
|
|
|
@ -88,7 +88,7 @@ struct StructWithCustomTypes : public JsonSerializable<StructWithCustomTypes> {
|
|||
};
|
||||
|
||||
/*!
|
||||
* \brief The NotJsonSerializable struct is used to tests (de)serialization for 3rd party structs (which do not
|
||||
* \brief The NotJsonSerializable struct is used to test (de)serialization for 3rd party structs (which do not
|
||||
* inherit from JsonSerializable instance). It is used in JsonGeneratorTests::test3rdPartyAdaption().
|
||||
* \remarks Imagine this struct would have been defined in a 3rd party header.
|
||||
*/
|
||||
|
@ -96,8 +96,20 @@ struct NotJsonSerializable {
|
|||
std::string butSerializableAnyways = "useful to adapt 3rd party structs";
|
||||
};
|
||||
|
||||
// make "NotJsonSerializable" serializable
|
||||
/*!
|
||||
* \brief The NestedNotJsonSerializable struct is used to test (de)serialization for 3rd party structs (which do not
|
||||
* inherit from JsonSerializable instance). It is used in JsonGeneratorTests::test3rdPartyAdaption().
|
||||
* \remarks Imagine this struct would have been defined in a 3rd party header.
|
||||
*/
|
||||
struct NestedNotJsonSerializable {
|
||||
NotJsonSerializable asMember;
|
||||
vector<NotJsonSerializable> asArrayElement;
|
||||
tuple<int, NotJsonSerializable> asTupleElement;
|
||||
};
|
||||
|
||||
// make "NotJsonSerializable" and "NestedNotJsonSerializable" serializable
|
||||
REFLECTIVE_RAPIDJSON_MAKE_JSON_SERIALIZABLE(NotJsonSerializable);
|
||||
REFLECTIVE_RAPIDJSON_MAKE_JSON_SERIALIZABLE(NestedNotJsonSerializable);
|
||||
|
||||
/*!
|
||||
* \brief The OtherNotJsonSerializable struct is used to test whether code for (de)serialization is generated for classes explicitely
|
||||
|
|
|
@ -77,26 +77,26 @@ void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_
|
|||
/*!
|
||||
* \brief Pushes the \a reflectable to the specified array.
|
||||
*/
|
||||
template <typename Type, Traits::DisableIf<std::is_base_of<JsonSerializable<Type>, Type>>...>
|
||||
template <typename Type, Traits::DisableIfAny<std::is_base_of<JsonSerializable<Type>, Type>, AdaptedJsonSerializable<Type>>...>
|
||||
void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value::Array &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator);
|
||||
|
||||
/*!
|
||||
* \brief Pushes the \a reflectable which has a custom type to the specified array.
|
||||
*/
|
||||
template <typename Type, Traits::EnableIf<std::is_base_of<JsonSerializable<Type>, Type>>...>
|
||||
template <typename Type, Traits::EnableIfAny<std::is_base_of<JsonSerializable<Type>, Type>, AdaptedJsonSerializable<Type>>...>
|
||||
void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value::Array &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator);
|
||||
|
||||
/*!
|
||||
* \brief Pushes the specified \a reflectable which has custom type as a member to the specified object.
|
||||
*/
|
||||
template <typename Type, Traits::EnableIf<std::is_base_of<JsonSerializable<Type>, Type>>...>
|
||||
template <typename Type, Traits::EnableIfAny<std::is_base_of<JsonSerializable<Type>, Type>, AdaptedJsonSerializable<Type>>...>
|
||||
void push(
|
||||
const Type &reflectable, const char *name, RAPIDJSON_NAMESPACE::Value::Object &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator);
|
||||
|
||||
/*!
|
||||
* \brief Pushes the specified \a reflectable as a member to the specified object.
|
||||
*/
|
||||
template <typename Type, Traits::DisableIf<std::is_base_of<JsonSerializable<Type>, Type>>...>
|
||||
template <typename Type, Traits::DisableIfAny<std::is_base_of<JsonSerializable<Type>, Type>, AdaptedJsonSerializable<Type>>...>
|
||||
void push(
|
||||
const Type &reflectable, const char *name, RAPIDJSON_NAMESPACE::Value::Object &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator);
|
||||
|
||||
|
@ -220,7 +220,7 @@ void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_
|
|||
/*!
|
||||
* \brief Pushes the specified \a reflectable which has a custom type to the specified array.
|
||||
*/
|
||||
template <typename Type, Traits::EnableIf<std::is_base_of<JsonSerializable<Type>, Type>>...>
|
||||
template <typename Type, Traits::EnableIfAny<std::is_base_of<JsonSerializable<Type>, Type>, AdaptedJsonSerializable<Type>>...>
|
||||
void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value::Array &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
|
||||
{
|
||||
RAPIDJSON_NAMESPACE::Value objectValue(RAPIDJSON_NAMESPACE::kObjectType);
|
||||
|
@ -232,7 +232,7 @@ void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value::Array &value, RAP
|
|||
/*!
|
||||
* \brief Pushes the specified \a reflectable to the specified array.
|
||||
*/
|
||||
template <typename Type, Traits::DisableIf<std::is_base_of<JsonSerializable<Type>, Type>>...>
|
||||
template <typename Type, Traits::DisableIfAny<std::is_base_of<JsonSerializable<Type>, Type>, AdaptedJsonSerializable<Type>>...>
|
||||
void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value::Array &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
|
||||
{
|
||||
RAPIDJSON_NAMESPACE::Value genericValue;
|
||||
|
@ -243,7 +243,7 @@ void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value::Array &value, RAP
|
|||
/*!
|
||||
* \brief Pushes the specified \a reflectable which has custom type as a member to the specified object.
|
||||
*/
|
||||
template <typename Type, Traits::EnableIf<std::is_base_of<JsonSerializable<Type>, Type>>...>
|
||||
template <typename Type, Traits::EnableIfAny<std::is_base_of<JsonSerializable<Type>, Type>, AdaptedJsonSerializable<Type>>...>
|
||||
void push(
|
||||
const Type &reflectable, const char *name, RAPIDJSON_NAMESPACE::Value::Object &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
|
||||
{
|
||||
|
@ -256,7 +256,7 @@ void push(
|
|||
/*!
|
||||
* \brief Pushes the specified \a reflectable as a member to the specified object.
|
||||
*/
|
||||
template <typename Type, Traits::DisableIf<std::is_base_of<JsonSerializable<Type>, Type>>...>
|
||||
template <typename Type, Traits::DisableIfAny<std::is_base_of<JsonSerializable<Type>, Type>, AdaptedJsonSerializable<Type>>...>
|
||||
void push(
|
||||
const Type &reflectable, const char *name, RAPIDJSON_NAMESPACE::Value::Object &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
|
||||
{
|
||||
|
@ -281,18 +281,9 @@ void pull(Type &reflectable, const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_N
|
|||
* \brief Pulls the \a reflectable which has a custom type from the specified value which is supposed and checked to contain an object.
|
||||
*/
|
||||
template <typename Type,
|
||||
Traits::DisableIfAny<std::is_integral<Type>, std::is_floating_point<Type>, std::is_pointer<Type>,
|
||||
Traits::DisableIfAny<std::is_integral<Type>, std::is_floating_point<Type>, std::is_pointer<Type>, Traits::IsSpecializationOf<Type, std::tuple>,
|
||||
Traits::All<Traits::IsIteratable<Type>, Traits::Not<Traits::IsSpecializationOf<Type, std::basic_string>>>>...>
|
||||
void pull(Type &reflectable, const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
|
||||
{
|
||||
if (!value.IsObject()) {
|
||||
if (errors) {
|
||||
errors->reportTypeMismatch<Type>(value.GetType());
|
||||
}
|
||||
return;
|
||||
}
|
||||
pull(reflectable, value.GetObject(), errors);
|
||||
}
|
||||
void pull(Type &reflectable, const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
|
||||
|
||||
/*!
|
||||
* \brief Pulls the integer/float/boolean from the specified value which is supposed and checked to contain the right type.
|
||||
|
@ -401,7 +392,7 @@ namespace Detail {
|
|||
* \remarks Assumes that the array bounds have been checked before (to match the size of the tuple).
|
||||
*/
|
||||
template <class Tuple, std::size_t N> struct TuplePullHelper {
|
||||
static void pull(Tuple &tuple, const RAPIDJSON_NAMESPACE::Value::Array &value, JsonDeserializationErrors *errors)
|
||||
static void pull(Tuple &tuple, const RAPIDJSON_NAMESPACE::Value::ConstArray value, JsonDeserializationErrors *errors)
|
||||
{
|
||||
TuplePullHelper<Tuple, N - 1>::pull(tuple, value, errors);
|
||||
JsonReflector::pull(std::get<N - 1>(tuple), value[N - 1], errors);
|
||||
|
@ -409,7 +400,7 @@ template <class Tuple, std::size_t N> struct TuplePullHelper {
|
|||
};
|
||||
|
||||
template <class Tuple> struct TuplePullHelper<Tuple, 1> {
|
||||
static void pull(Tuple &tuple, const RAPIDJSON_NAMESPACE::Value::Array &value, JsonDeserializationErrors *errors)
|
||||
static void pull(Tuple &tuple, const RAPIDJSON_NAMESPACE::Value::ConstArray value, JsonDeserializationErrors *errors)
|
||||
{
|
||||
JsonReflector::pull(std::get<0>(tuple), value[0], errors);
|
||||
}
|
||||
|
@ -420,7 +411,7 @@ template <class Tuple> struct TuplePullHelper<Tuple, 1> {
|
|||
* \brief Pulls the speciified \a reflectable which is tuple from the specified value which is checked to contain an array.
|
||||
*/
|
||||
template <typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::tuple>>...>
|
||||
void pull(Type &reflectable, rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
|
||||
void pull(Type &reflectable, const rapidjson::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
|
||||
{
|
||||
if (!value.IsArray()) {
|
||||
if (errors) {
|
||||
|
@ -459,7 +450,7 @@ inline void pull(Type &reflectable, const char *name, const rapidjson::GenericVa
|
|||
JsonDeserializationErrors *errors)
|
||||
{
|
||||
// find member
|
||||
auto member = value.FindMember(name);
|
||||
const auto member = value.FindMember(name);
|
||||
if (member == value.MemberEnd()) {
|
||||
return; // TODO: handle member missing
|
||||
}
|
||||
|
@ -472,7 +463,7 @@ inline void pull(Type &reflectable, const char *name, const rapidjson::GenericVa
|
|||
}
|
||||
|
||||
// actually pull value for member
|
||||
pull<Type>(reflectable, value.FindMember(name)->value, errors);
|
||||
pull<Type>(reflectable, member->value, errors);
|
||||
|
||||
// restore previous error context
|
||||
if (errors) {
|
||||
|
@ -480,6 +471,23 @@ inline void pull(Type &reflectable, const char *name, const rapidjson::GenericVa
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Pulls the \a reflectable which has a custom type from the specified value which is supposed and checked to contain an object.
|
||||
*/
|
||||
template <typename Type,
|
||||
Traits::DisableIfAny<std::is_integral<Type>, std::is_floating_point<Type>, std::is_pointer<Type>, Traits::IsSpecializationOf<Type, std::tuple>,
|
||||
Traits::All<Traits::IsIteratable<Type>, Traits::Not<Traits::IsSpecializationOf<Type, std::basic_string>>>>...>
|
||||
void pull(Type &reflectable, const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors)
|
||||
{
|
||||
if (!value.IsObject()) {
|
||||
if (errors) {
|
||||
errors->reportTypeMismatch<Type>(value.GetType());
|
||||
}
|
||||
return;
|
||||
}
|
||||
pull(reflectable, value.GetObject(), errors);
|
||||
}
|
||||
|
||||
// define functions providing high-level JSON serialization
|
||||
|
||||
/*!
|
||||
|
@ -584,9 +592,9 @@ Type fromJson(const char *json, std::size_t jsonSize, JsonDeserializationErrors
|
|||
/*!
|
||||
* \brief Deserializes the specified JSON from an std::string to \tparam Type.
|
||||
*/
|
||||
template <typename Type> Type fromJson(const std::string &json)
|
||||
template <typename Type> Type fromJson(const std::string &json, JsonDeserializationErrors *errors)
|
||||
{
|
||||
return fromJson<Type>(json.data(), json.size());
|
||||
return fromJson<Type>(json.data(), json.size(), errors);
|
||||
}
|
||||
|
||||
} // namespace JsonReflector
|
||||
|
|
Loading…
Reference in New Issue