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:
parent
888feee3f4
commit
4a8ebc99a3
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -1,10 +0,0 @@
|
|||
#include "./reflect.h"
|
||||
|
||||
using namespace RAPIDJSON_NAMESPACE;
|
||||
|
||||
namespace ReflectiveRapidJSON {
|
||||
|
||||
namespace Reflector {
|
||||
}
|
||||
|
||||
} // namespace ReflectiveRapidJSON
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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}}"));
|
|
@ -45,5 +45,6 @@ include(WindowsResources)
|
|||
include(AppTarget)
|
||||
include(TestTarget)
|
||||
include(ShellCompletion)
|
||||
include(Doxygen)
|
||||
include(ConfigHeader)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue