Rename Reflectable -> JSONSerializable

This allows to provide multiple independently
functional reflection features by simply using
different base classes for them.
This commit is contained in:
Martchus 2017-10-23 00:41:10 +02:00
parent 888feee3f4
commit 4a8ebc99a3
10 changed files with 101 additions and 64 deletions

View File

@ -5,17 +5,16 @@ set(META_PROJECT_TYPE library)
# add project files
set(HEADER_FILES
reflect.h
reflectable.h
jsonreflector.h
jsonserializable.h
)
set(SRC_FILES
reflect.cpp
)
set(TEST_HEADER_FILES
)
set(TEST_SRC_FILES
tests/cppunit.cpp
tests/reflector.cpp
tests/jsonreflector.cpp
)
set(DOC_FILES
README.md

View File

@ -1,5 +1,5 @@
#ifndef REFLECTIVE_RAPIDJSON_REFLECT_H
#define REFLECTIVE_RAPIDJSON_REFLECT_H
#ifndef REFLECTIVE_RAPIDJSON_JSON_REFLECTOR_H
#define REFLECTIVE_RAPIDJSON_JSON_REFLECTOR_H
#include <c++utilities/conversion/types.h>
#include <c++utilities/misc/traits.h>
@ -27,7 +27,7 @@ constexpr ErrorFlags operator|(ErrorFlags lhs, ErrorFlags rhs)
return static_cast<ErrorFlags>(static_cast<unsigned char>(lhs) | static_cast<unsigned char>(rhs));
}
template <typename Type> struct Reflectable;
template <typename Type> struct JSONSerializable;
inline RAPIDJSON_NAMESPACE::StringBuffer documentToString(RAPIDJSON_NAMESPACE::Document &document)
{
@ -226,7 +226,7 @@ inline void pull(Type &reflectable, const char *name, const rapidjson::GenericVa
// define functions providing high-level JSON serialization
template <typename Type, Traits::EnableIfAny<std::is_base_of<Reflectable<Type>, Type>>...>
template <typename Type, Traits::EnableIfAny<std::is_base_of<JSONSerializable<Type>, Type>>...>
RAPIDJSON_NAMESPACE::StringBuffer toJson(const Type &reflectable)
{
RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kObjectType);
@ -260,7 +260,7 @@ template <typename Type, Traits::EnableIfAny<std::is_same<Type, const char *>>..
// define functions providing high-level JSON deserialization
template <typename Type, Traits::EnableIfAny<std::is_base_of<Reflectable<Type>, Type>>...> Type fromJson(const char *json, std::size_t jsonSize)
template <typename Type, Traits::EnableIfAny<std::is_base_of<JSONSerializable<Type>, Type>>...> Type fromJson(const char *json, std::size_t jsonSize)
{
RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kObjectType);
document.Parse(json, jsonSize);
@ -290,19 +290,6 @@ template <typename Type> Type fromJson(const std::string &json)
}
} // namespace Reflector
} // namespace ReflectiveRapidJSON
#define REFLECT(Type) \
namespace Reflector { \
template <> \
void push<Type>(const Type &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator); \
template <> \
void add<Type>( \
const Type &reflectable, const char *name, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator); \
template <> std::string toJson<Type>(const Type &reflectable); \
template <> Type fromJson<Type>(const char *json, std::size_t jsonSize); \
template <> Type fromJson<Type>(const std::string &json); \
}
#endif // REFLECTIVE_RAPIDJSON_REFLECT_H
#endif // REFLECTIVE_RAPIDJSON_JSON_REFLECTOR_H

58
lib/jsonserializable.h Normal file
View File

@ -0,0 +1,58 @@
#ifndef REFLECTIVE_RAPIDJSON_JSON_SERIALIZABLE_H
#define REFLECTIVE_RAPIDJSON_JSON_SERIALIZABLE_H
#include "./jsonreflector.h"
#include <rapidjson/document.h>
#include <string>
namespace ReflectiveRapidJSON {
template <typename Type> struct JSONSerializable {
// RapidJSON-level API
void push(RAPIDJSON_NAMESPACE::Value &container);
void push(RAPIDJSON_NAMESPACE::Value &container, const char *name);
// high-level API
RAPIDJSON_NAMESPACE::StringBuffer toJson() const;
static Type fromJson(const char *json, std::size_t jsonSize);
static Type fromJson(const char *json);
static Type fromJson(const std::string &json);
static constexpr const char *qualifiedName = "ReflectiveRapidJSON::JSONSerializable";
};
template <typename Type> void JSONSerializable<Type>::push(RAPIDJSON_NAMESPACE::Value &container)
{
return Reflector::push<Type>(*this, container);
}
template <typename Type> void JSONSerializable<Type>::push(RAPIDJSON_NAMESPACE::Value &container, const char *name)
{
return Reflector::push<Type>(*this, name, container);
}
template <typename Type> RAPIDJSON_NAMESPACE::StringBuffer JSONSerializable<Type>::toJson() const
{
return Reflector::toJson<Type>(static_cast<const Type &>(*this));
}
template <typename Type> Type JSONSerializable<Type>::fromJson(const char *json, std::size_t jsonSize)
{
return Reflector::fromJson<Type>(json, jsonSize);
}
template <typename Type> Type JSONSerializable<Type>::fromJson(const char *json)
{
return Reflector::fromJson<Type>(json, std::strlen(json));
}
template <typename Type> Type JSONSerializable<Type>::fromJson(const std::string &json)
{
return Reflector::fromJson<Type>(json.data(), json.size());
}
} // namespace ReflectiveRapidJSON
#endif // REFLECTIVE_RAPIDJSON_JSON_SERIALIZABLE_H

View File

@ -1,10 +0,0 @@
#include "./reflect.h"
using namespace RAPIDJSON_NAMESPACE;
namespace ReflectiveRapidJSON {
namespace Reflector {
}
} // namespace ReflectiveRapidJSON

View File

@ -9,7 +9,7 @@
namespace ReflectiveRapidJSON {
template <typename Type> struct Reflectable {
template <typename Type> struct JSONSerializable {
// RapidJSON-level API
void push(RAPIDJSON_NAMESPACE::Value &container);
void push(RAPIDJSON_NAMESPACE::Value &container, const char *name);
@ -21,32 +21,32 @@ template <typename Type> struct Reflectable {
static Type fromJson(const std::string &json);
};
template <typename Type> void Reflectable<Type>::push(RAPIDJSON_NAMESPACE::Value &container)
template <typename Type> void JSONSerializable<Type>::push(RAPIDJSON_NAMESPACE::Value &container)
{
return Reflector::push<Type>(*this, container);
}
template <typename Type> void Reflectable<Type>::push(RAPIDJSON_NAMESPACE::Value &container, const char *name)
template <typename Type> void JSONSerializable<Type>::push(RAPIDJSON_NAMESPACE::Value &container, const char *name)
{
return Reflector::push<Type>(*this, name, container);
}
template <typename Type> RAPIDJSON_NAMESPACE::StringBuffer Reflectable<Type>::toJson() const
template <typename Type> RAPIDJSON_NAMESPACE::StringBuffer JSONSerializable<Type>::toJson() const
{
return Reflector::toJson<Type>(static_cast<const Type &>(*this));
}
template <typename Type> Type Reflectable<Type>::fromJson(const char *json, std::size_t jsonSize)
template <typename Type> Type JSONSerializable<Type>::fromJson(const char *json, std::size_t jsonSize)
{
return Reflector::fromJson<Type>(json, jsonSize);
}
template <typename Type> Type Reflectable<Type>::fromJson(const char *json)
template <typename Type> Type JSONSerializable<Type>::fromJson(const char *json)
{
return Reflector::fromJson<Type>(json, std::strlen(json));
}
template <typename Type> Type Reflectable<Type>::fromJson(const std::string &json)
template <typename Type> Type JSONSerializable<Type>::fromJson(const std::string &json)
{
return Reflector::fromJson<Type>(json.data(), json.size());
}

View File

@ -1,6 +1,5 @@
#include "../reflectable.h"
#include "resources/config.h"
#include "../jsonreflector.h"
#include "../jsonserializable.h"
#include <c++utilities/conversion/stringbuilder.h>
#include <c++utilities/conversion/stringconversion.h>
@ -31,7 +30,7 @@ using namespace ReflectiveRapidJSON;
/// \cond
// define some structs for testing serialization
struct TestObject : public Reflectable<TestObject> {
struct TestObject : public JSONSerializable<TestObject> {
int number;
double number2;
vector<int> numbers;
@ -39,12 +38,12 @@ struct TestObject : public Reflectable<TestObject> {
bool boolean;
};
struct NestingObject : public Reflectable<NestingObject> {
struct NestingObject : public JSONSerializable<NestingObject> {
string name;
TestObject testObj;
};
struct NestingArray : public Reflectable<NestingArray> {
struct NestingArray : public JSONSerializable<NestingArray> {
string name;
vector<TestObject> testObjects;
};
@ -104,8 +103,8 @@ template <> inline void pull<NestingArray>(NestingArray &reflectable, const Gene
* \brief The ReflectorTests class tests RapidJSON wrapper which is used to ease code generation.
* \remarks In this tests, no reflection or code generation is involved yet.
*/
class ReflectorTests : public TestFixture {
CPPUNIT_TEST_SUITE(ReflectorTests);
class JSONReflectorTests : public TestFixture {
CPPUNIT_TEST_SUITE(JSONReflectorTests);
CPPUNIT_TEST(experiment);
CPPUNIT_TEST(testSerializePrimitives);
CPPUNIT_TEST(testSerializeSimpleObjects);
@ -130,20 +129,20 @@ public:
private:
};
CPPUNIT_TEST_SUITE_REGISTRATION(ReflectorTests);
CPPUNIT_TEST_SUITE_REGISTRATION(JSONReflectorTests);
void ReflectorTests::setUp()
void JSONReflectorTests::setUp()
{
}
void ReflectorTests::tearDown()
void JSONReflectorTests::tearDown()
{
}
/*!
* \brief Not a real test, just some assertions for experimenting with the RapidJSON library.
*/
void ReflectorTests::experiment()
void JSONReflectorTests::experiment()
{
Document doc(kArrayType);
Document::AllocatorType &alloc = doc.GetAllocator();
@ -170,7 +169,7 @@ void ReflectorTests::experiment()
/*!
* \brief Tests serializing strings, numbers, arrays and boolean.
*/
void ReflectorTests::testSerializePrimitives()
void JSONReflectorTests::testSerializePrimitives()
{
Document doc(kArrayType);
Document::AllocatorType &alloc = doc.GetAllocator();
@ -201,7 +200,7 @@ void ReflectorTests::testSerializePrimitives()
/*!
* \brief Tests serializing objects.
*/
void ReflectorTests::testSerializeSimpleObjects()
void JSONReflectorTests::testSerializeSimpleObjects()
{
TestObject testObj;
testObj.number = 42;
@ -216,7 +215,7 @@ void ReflectorTests::testSerializeSimpleObjects()
/*!
* \brief Tests serializing nested object and arrays.
*/
void ReflectorTests::testSerializeNestedObjects()
void JSONReflectorTests::testSerializeNestedObjects()
{
NestingObject nestingObj;
nestingObj.name = "nesting";
@ -242,7 +241,7 @@ void ReflectorTests::testSerializeNestedObjects()
/*!
* \brief Tests deserializing strings, numbers (int, float, double) and boolean.
*/
void ReflectorTests::testDeserializePrimitives()
void JSONReflectorTests::testDeserializePrimitives()
{
Document doc(kArrayType);
@ -274,7 +273,7 @@ void ReflectorTests::testDeserializePrimitives()
/*!
* \brief Tests deserializing simple objects.
*/
void ReflectorTests::testDeserializeSimpleObjects()
void JSONReflectorTests::testDeserializeSimpleObjects()
{
const TestObject testObj(
TestObject::fromJson("{\"number\":42,\"number2\":3.141592653589793,\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false}"));
@ -289,7 +288,7 @@ void ReflectorTests::testDeserializeSimpleObjects()
/*!
* \brief Tests deserializing nested objects and arrays.
*/
void ReflectorTests::testDeserializeNestedObjects()
void JSONReflectorTests::testDeserializeNestedObjects()
{
const NestingObject nestingObj(NestingObject::fromJson("{\"name\":\"nesting\",\"testObj\":{\"number\":42,\"number2\":3.141592653589793,"
"\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false}}"));

View File

@ -45,5 +45,6 @@ include(WindowsResources)
include(AppTarget)
include(TestTarget)
include(ShellCompletion)
include(Doxygen)
include(ConfigHeader)

View File

@ -1,6 +1,8 @@
#include "./generator.h"
#include "./frontendaction.h"
#include "../lib/jsonserializable.h"
#include <c++utilities/application/global.h>
#include <c++utilities/conversion/stringbuilder.h>
@ -62,8 +64,8 @@ void JSONSerializationCodeGenerator::addDeclaration(clang::Decl *decl)
if (!record->hasDefinition()) {
return;
}
// add classes derived from any instantiation of "ReflectiveRapidJSON::Reflectable"
if (inheritsFromInstantiationOf(record, "ReflectiveRapidJSON::Reflectable")) {
// add classes derived from any instantiation of "ReflectiveRapidJSON::JSONSerializable"
if (inheritsFromInstantiationOf(record, JSONSerializable<void>::qualifiedName)) {
m_relevantClasses.emplace_back(record->getQualifiedNameAsString(), record);
}
break;
@ -86,7 +88,7 @@ void JSONSerializationCodeGenerator::generate(ostream &os) const
"namespace Reflector {\n";
// add push and pull functions for each class, for an example of the resulting
// output, see ../lib/tests/reflector.cpp (code under comment "pretend serialization code...")
// output, see ../lib/tests/jsonserializable.cpp (code under comment "pretend serialization code...")
for (const RelevantClass &relevantClass : m_relevantClasses) {
// print push method
os << "template <> inline void push<::" << relevantClass.qualifiedName << ">(const " << relevantClass.qualifiedName

View File

@ -36,7 +36,8 @@ inline CodeGenerator::CodeGenerator()
}
/*!
* \brief The JSONSerializationCodeGenerator class generates code for JSON (de)serialization.
* \brief The JSONSerializationCodeGenerator class generates code for JSON (de)serialization
* of objects inheriting from an instantiation of JSONSerializable.
*/
class JSONSerializationCodeGenerator : public CodeGenerator {
public:

View File

@ -2,13 +2,13 @@
#define SOME_STRUCTS_H
//#include <string>
#include "../../lib/reflectable.h"
#include "../../lib/jsonserializable.h"
namespace TestNamespace1 {
#define SOME_MACRO
struct Person : public ReflectiveRapidJSON::Reflectable<Person>
struct Person : public ReflectiveRapidJSON::JSONSerializable<Person>
{
SOME_MACRO
//std::string name;