Allow direct serialization of iteratables

This commit is contained in:
Martchus 2017-11-18 00:28:24 +01:00
parent 69d4fa193f
commit 86a577748e
2 changed files with 71 additions and 12 deletions

View File

@ -590,9 +590,10 @@ void pull(Type &reflectable, const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_N
// define functions providing high-level JSON serialization
/*!
* \brief Serializes the specified \a reflectable which has a custom type.
* \brief Serializes the specified \a reflectable which has a custom type or can be mapped to and object.
*/
template <typename Type, Traits::EnableIf<IsJsonSerializable<Type>>...> RAPIDJSON_NAMESPACE::StringBuffer toJson(const Type &reflectable)
template <typename Type, Traits::EnableIfAny<IsJsonSerializable<Type>, IsMapOrHash<Type>>...>
RAPIDJSON_NAMESPACE::StringBuffer toJson(const Type &reflectable)
{
RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kObjectType);
RAPIDJSON_NAMESPACE::Document::Object object(document.GetObject());
@ -614,7 +615,7 @@ RAPIDJSON_NAMESPACE::StringBuffer toJson(Type reflectable)
/*!
* \brief Serializes the specified \a reflectable which is an std::string.
*/
template <typename Type, Traits::EnableIfAny<std::is_same<Type, std::string>>...>
template <typename Type, Traits::EnableIf<std::is_same<Type, std::string>>...>
RAPIDJSON_NAMESPACE::StringBuffer toJson(const std::string &reflectable)
{
RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kStringType);
@ -625,19 +626,29 @@ RAPIDJSON_NAMESPACE::StringBuffer toJson(const std::string &reflectable)
/*!
* \brief Serializes the specified \a reflectable which is a C-string.
*/
template <typename Type, Traits::EnableIfAny<std::is_same<Type, const char *>>...> RAPIDJSON_NAMESPACE::StringBuffer toJson(const char *reflectable)
template <typename Type, Traits::EnableIf<std::is_same<Type, const char *>>...> RAPIDJSON_NAMESPACE::StringBuffer toJson(const char *reflectable)
{
RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kStringType);
document.SetString(RAPIDJSON_NAMESPACE::StringRef(reflectable), document.GetAllocator());
return serializeJsonDocToString(document);
}
/*!
* \brief Serializes the specified \a reflectable which can be mapped to an array.
*/
template <typename Type, Traits::EnableIf<IsArray<Type>>...> RAPIDJSON_NAMESPACE::StringBuffer toJson(const Type &reflectable)
{
RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kArrayType);
push(reflectable, document, document.GetAllocator());
return serializeJsonDocToString(document);
}
// define functions providing high-level JSON deserialization
/*!
* \brief Deserializes the specified JSON to \tparam Type which is a custom type.
* \brief Deserializes the specified JSON to \tparam Type which is a custom type or can be mapped to an object.
*/
template <typename Type, Traits::EnableIf<IsJsonSerializable<Type>>...>
template <typename Type, Traits::EnableIfAny<IsJsonSerializable<Type>, IsMapOrHash<Type>>...>
Type fromJson(const char *json, std::size_t jsonSize, JsonDeserializationErrors *errors = nullptr)
{
RAPIDJSON_NAMESPACE::Document doc(parseJsonDocFromString(json, jsonSize));
@ -657,7 +668,7 @@ Type fromJson(const char *json, std::size_t jsonSize, JsonDeserializationErrors
* \brief Deserializes the specified JSON to \tparam Type which is an integer, float or boolean.
*/
template <typename Type, Traits::EnableIfAny<std::is_integral<Type>, std::is_floating_point<Type>>...>
Type fromJson(const char *json, std::size_t jsonSize, JsonDeserializationErrors *errors)
Type fromJson(const char *json, std::size_t jsonSize, JsonDeserializationErrors *errors = nullptr)
{
RAPIDJSON_NAMESPACE::Document doc(parseJsonDocFromString(json, jsonSize));
if (!doc.Is<Type>()) {
@ -673,8 +684,8 @@ Type fromJson(const char *json, std::size_t jsonSize, JsonDeserializationErrors
/*!
* \brief Deserializes the specified JSON to \tparam Type which is a std::string.
*/
template <typename Type, Traits::EnableIfAny<std::is_same<Type, std::string>>...>
Type fromJson(const char *json, std::size_t jsonSize, JsonDeserializationErrors *errors)
template <typename Type, Traits::EnableIf<std::is_same<Type, std::string>>...>
Type fromJson(const char *json, std::size_t jsonSize, JsonDeserializationErrors *errors = nullptr)
{
RAPIDJSON_NAMESPACE::Document doc(parseJsonDocFromString(json, jsonSize));
if (!doc.IsString()) {
@ -687,10 +698,37 @@ Type fromJson(const char *json, std::size_t jsonSize, JsonDeserializationErrors
return doc.GetString();
}
/*!
* \brief Deserializes the specified JSON to \tparam Type which can be mapped to an array.
*/
template <typename Type, Traits::EnableIf<IsArray<Type>>...>
Type fromJson(const char *json, std::size_t jsonSize, JsonDeserializationErrors *errors = nullptr)
{
RAPIDJSON_NAMESPACE::Document doc(parseJsonDocFromString(json, jsonSize));
if (!doc.IsArray()) {
if (errors) {
errors->reportTypeMismatch<Type>(doc.GetType());
}
return Type();
}
Type res;
pull<Type>(res, doc.GetArray(), errors);
return res;
}
/*!
* \brief Deserializes the specified JSON from an null-terminated C-string to \tparam Type.
*/
template <typename Type> Type fromJson(const char *json, JsonDeserializationErrors *errors = nullptr)
{
return fromJson<Type>(json, std::strlen(json), errors);
}
/*!
* \brief Deserializes the specified JSON from an std::string to \tparam Type.
*/
template <typename Type> Type fromJson(const std::string &json, JsonDeserializationErrors *errors)
template <typename Type> Type fromJson(const std::string &json, JsonDeserializationErrors *errors = nullptr)
{
return fromJson<Type>(json.data(), json.size(), errors);
}

View File

@ -279,6 +279,7 @@ void JsonReflectorTests::testSerializeNestedObjects()
CPPUNIT_ASSERT_EQUAL(
"{\"name\":\"nesting\",\"testObj\":{\"number\":42,\"number2\":3.141592653589793,\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false,\"someMap\":{},\"someHash\":{}}}"s,
string(nestingObj.toJson().GetString()));
NestingArray nestingArray;
nestingArray.name = "nesting2";
nestingArray.testObjects.emplace_back(testObj);
@ -287,6 +288,12 @@ void JsonReflectorTests::testSerializeNestedObjects()
CPPUNIT_ASSERT_EQUAL(
"{\"name\":\"nesting2\",\"testObjects\":[{\"number\":42,\"number2\":3.141592653589793,\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false,\"someMap\":{},\"someHash\":{}},{\"number\":43,\"number2\":3.141592653589793,\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false,\"someMap\":{},\"someHash\":{}}]}"s,
string(nestingArray.toJson().GetString()));
vector<TestObject> nestedInVector;
nestedInVector.emplace_back(testObj);
CPPUNIT_ASSERT_EQUAL(
"[{\"number\":42,\"number2\":3.141592653589793,\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false,\"someMap\":{},\"someHash\":{}}]"s,
string(JsonReflector::toJson(nestedInVector).GetString()));
}
void JsonReflectorTests::testSerializeUniquePtr()
@ -419,9 +426,12 @@ void JsonReflectorTests::testDeserializeSimpleObjects()
*/
void JsonReflectorTests::testDeserializeNestedObjects()
{
JsonDeserializationErrors errors;
const NestingObject nestingObj(NestingObject::fromJson("{\"name\":\"nesting\",\"testObj\":{\"number\":42,\"number2\":3.141592653589793,"
"\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false}}"));
"\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false}}",
&errors));
const TestObject &testObj = nestingObj.testObj;
CPPUNIT_ASSERT_EQUAL(0_st, errors.size());
CPPUNIT_ASSERT_EQUAL("nesting"s, nestingObj.name);
CPPUNIT_ASSERT_EQUAL(42, testObj.number);
CPPUNIT_ASSERT_EQUAL(3.141592653589793, testObj.number2);
@ -431,8 +441,10 @@ void JsonReflectorTests::testDeserializeNestedObjects()
const NestingArray nestingArray(NestingArray::fromJson("{\"name\":\"nesting2\",\"testObjects\":[{\"number\":42,\"number2\":3.141592653589793,"
"\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false},{\"number\":43,\"number2\":3."
"141592653589793,\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false}]}"));
"141592653589793,\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false}]}",
&errors));
const vector<TestObject> &testObjects = nestingArray.testObjects;
CPPUNIT_ASSERT_EQUAL(0_st, errors.size());
CPPUNIT_ASSERT_EQUAL("nesting2"s, nestingArray.name);
CPPUNIT_ASSERT_EQUAL(2_st, testObjects.size());
CPPUNIT_ASSERT_EQUAL(42, testObjects[0].number);
@ -443,6 +455,15 @@ void JsonReflectorTests::testDeserializeNestedObjects()
CPPUNIT_ASSERT_EQUAL("test"s, testObj.text);
CPPUNIT_ASSERT_EQUAL(false, testObj.boolean);
}
const auto nestedInVector(JsonReflector::fromJson<vector<TestObject>>(
"[{\"number\":42,\"number2\":3.141592653589793,\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false,\"someMap\":{},\"someHash\":{}}]",
&errors));
CPPUNIT_ASSERT_EQUAL(0_st, errors.size());
CPPUNIT_ASSERT_EQUAL(1_st, nestedInVector.size());
CPPUNIT_ASSERT_EQUAL(42, nestedInVector[0].number);
CPPUNIT_ASSERT_EQUAL(4_st, nestedInVector[0].numbers.size());
CPPUNIT_ASSERT_EQUAL("test"s, nestedInVector[0].text);
}
void JsonReflectorTests::testDeserializeUniquePtr()