diff --git a/CMakeLists.txt b/CMakeLists.txt index ceadcf9..d25af07 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,7 @@ else() message(FATAL_ERROR "Specified directory for c++utilities sources \"${BUNDLED_CPP_UTILITIES_PATH}\" does not exist.") endif() -# add header-only library containing JSONSerializable and helper for using RapidJSON +# add header-only library containing JsonSerializable and helper for using RapidJSON add_subdirectory(lib) # allow inclusion of CMake modules from that lib in other parts of the project set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/lib/cmake/modules" "${CMAKE_MODULE_PATH}") diff --git a/README.md b/README.md index 85ec517..375273c 100644 --- a/README.md +++ b/README.md @@ -13,21 +13,21 @@ generator. ## Usage This example shows how the library can be used to make a `struct` serializable: ``` -#include +#include // define structures, eg. -struct TestObject : public JSONSerializable { +struct TestObject : public JsonSerializable { int number; double number2; vector numbers; string text; bool boolean; }; -struct NestingObject : public JSONSerializable { +struct NestingObject : public JsonSerializable { string name; TestObject testObj; }; -struct NestingArray : public JSONSerializable { +struct NestingArray : public JsonSerializable { string name; vector testObjects; }; @@ -75,10 +75,10 @@ to the sources of your target. Of course this can be skipped if not required/wan The same example as above. However, this time Boost.Hana is used - so it doesn't require invoking the generator. ``` -#include " +#include " // define structures using BOOST_HANA_DEFINE_STRUCT, eg. -struct TestObject : public JSONSerializable { +struct TestObject : public JsonSerializable { BOOST_HANA_DEFINE_STRUCT(TestObject, (int, number), (double, number2), @@ -87,13 +87,13 @@ struct TestObject : public JSONSerializable { (bool, boolean) ); }; -struct NestingObject : public JSONSerializable { +struct NestingObject : public JsonSerializable { BOOST_HANA_DEFINE_STRUCT(NestingObject, (string, name), (TestObject, testObj) ); }; -struct NestingArray : public JSONSerializable { +struct NestingArray : public JsonSerializable { BOOST_HANA_DEFINE_STRUCT(NestingArray, (string, name), (vector, testObjects) @@ -108,7 +108,7 @@ cout << "JSON: " << obj.toJson().GetString(); const auto obj = NestingArray::fromJson(...); ``` -So the usage remains the same. +So beside the `BOOST_HANA_DEFINE_STRUCT` macro, the usage remains the same. ## Install instructions diff --git a/generator/README.md b/generator/README.md deleted file mode 100644 index df9d6c1..0000000 --- a/generator/README.md +++ /dev/null @@ -1 +0,0 @@ -# skel diff --git a/generator/codegenerator.cpp b/generator/codegenerator.cpp index 2a87cfb..54665b0 100644 --- a/generator/codegenerator.cpp +++ b/generator/codegenerator.cpp @@ -1,6 +1,6 @@ #include "./codegenerator.h" -#include "../lib/jsonserializable.h" +#include "../lib/json/serializable.h" #include @@ -58,8 +58,8 @@ void JSONSerializationCodeGenerator::addDeclaration(clang::Decl *decl) if (!record->hasDefinition()) { return; } - // add classes derived from any instantiation of "ReflectiveRapidJSON::JSONSerializable" - if (inheritsFromInstantiationOf(record, JSONSerializable::qualifiedName)) { + // add classes derived from any instantiation of "ReflectiveRapidJSON::JsonSerializable" + if (inheritsFromInstantiationOf(record, JsonSerializable::qualifiedName)) { m_relevantClasses.emplace_back(record->getQualifiedNameAsString(), record); } break; @@ -105,7 +105,8 @@ void JSONSerializationCodeGenerator::generate(ostream &os) const // print pull method os << "template <> inline void pull<::" << relevantClass.qualifiedName << ">(::" << relevantClass.qualifiedName - << " &reflectable, const ::RAPIDJSON_NAMESPACE::GenericValue<::RAPIDJSON_NAMESPACE::UTF8>::ConstObject &value, JSONParseErrors " + << " &reflectable, const ::RAPIDJSON_NAMESPACE::GenericValue<::RAPIDJSON_NAMESPACE::UTF8>::ConstObject &value, " + "JsonDeserializationErrors " "*errors)\n{\n" " // pull base classes\n"; for (const RelevantClass *baseClass : relevantBases) { diff --git a/generator/codegenerator.h b/generator/codegenerator.h index a5506b7..ad06131 100644 --- a/generator/codegenerator.h +++ b/generator/codegenerator.h @@ -48,7 +48,7 @@ inline CodeFactory &CodeGenerator::factory() const /*! * \brief The JSONSerializationCodeGenerator class generates code for JSON (de)serialization - * of objects inheriting from an instantiation of JSONSerializable. + * of objects inheriting from an instantiation of JsonSerializable. */ class JSONSerializationCodeGenerator : public CodeGenerator { public: diff --git a/generator/testfiles/some_structs.h b/generator/testfiles/some_structs.h index f1fe9f4..7c42f75 100644 --- a/generator/testfiles/some_structs.h +++ b/generator/testfiles/some_structs.h @@ -2,13 +2,13 @@ #define SOME_STRUCTS_H //#include -#include "../../lib/jsonserializable.h" +#include "../../lib/json/serializable.h" namespace TestNamespace1 { #define SOME_MACRO -struct Person : public ReflectiveRapidJSON::JSONSerializable +struct Person : public ReflectiveRapidJSON::JsonSerializable { SOME_MACRO //std::string name; diff --git a/generator/testfiles/some_structs_json_serialization.h b/generator/testfiles/some_structs_json_serialization.h index c4b009b..97ec12d 100644 --- a/generator/testfiles/some_structs_json_serialization.h +++ b/generator/testfiles/some_structs_json_serialization.h @@ -9,7 +9,7 @@ template <> inline void push<::TestNamespace1::Person>(const ::TestNamespace1::P push(reflectable.age, "age", value, allocator); push(reflectable.alive, "alive", value, allocator); } -template <> inline void pull<::TestNamespace1::Person>(::TestNamespace1::Person &reflectable, const ::RAPIDJSON_NAMESPACE::GenericValue<::RAPIDJSON_NAMESPACE::UTF8>::ConstObject &value, JSONParseErrors *errors) +template <> inline void pull<::TestNamespace1::Person>(::TestNamespace1::Person &reflectable, const ::RAPIDJSON_NAMESPACE::GenericValue<::RAPIDJSON_NAMESPACE::UTF8>::ConstObject &value, JsonDeserializationErrors *errors) { // pull base classes // set error context for current record diff --git a/generator/tests/jsongenerator.cpp b/generator/tests/jsongenerator.cpp index 8b9dac4..c12c75e 100644 --- a/generator/tests/jsongenerator.cpp +++ b/generator/tests/jsongenerator.cpp @@ -159,7 +159,7 @@ void OverallTests::testSingleInheritence() CPPUNIT_ASSERT_EQUAL(expectedJSONForDerived, string(as(test).toJson().GetString())); // test deserialization - const DerivedTestStruct parsedTest(JSONSerializable::fromJson(expectedJSONForDerived)); + const DerivedTestStruct parsedTest(JsonSerializable::fromJson(expectedJSONForDerived)); CPPUNIT_ASSERT_EQUAL(test.someInt, parsedTest.someInt); CPPUNIT_ASSERT_EQUAL(test.someString, parsedTest.someString); CPPUNIT_ASSERT_EQUAL(test.yetAnotherString, parsedTest.yetAnotherString); @@ -184,7 +184,7 @@ void OverallTests::testMultipleInheritence() CPPUNIT_ASSERT_EQUAL(expectedJSONForDerived, string(as(test).toJson().GetString())); // test deserialization - const MultipleDerivedTestStruct parsedTest(JSONSerializable::fromJson(expectedJSONForDerived)); + const MultipleDerivedTestStruct parsedTest(JsonSerializable::fromJson(expectedJSONForDerived)); CPPUNIT_ASSERT_EQUAL(test.someInt, parsedTest.someInt); CPPUNIT_ASSERT_EQUAL(test.someString, parsedTest.someString); CPPUNIT_ASSERT_EQUAL(test.yetAnotherString, parsedTest.yetAnotherString); diff --git a/generator/tests/structs.h b/generator/tests/structs.h index d9105f6..46a3ae0 100644 --- a/generator/tests/structs.h +++ b/generator/tests/structs.h @@ -1,7 +1,7 @@ #ifndef REFLECTIVE_RAPIDJSON_TESTS_STRUCTS_H #define REFLECTIVE_RAPIDJSON_TESTS_STRUCTS_H -#include "../../lib/jsonserializable.h" +#include "../../lib/json/serializable.h" #include #include @@ -12,37 +12,37 @@ using namespace std; using namespace ReflectiveRapidJSON; /*! - * \brief The TestStruct struct inherits from JSONSerializable and should hence have functional fromJson() + * \brief The TestStruct struct inherits from JsonSerializable and should hence have functional fromJson() * and toJson() methods. This is asserted in OverallTests::testIncludingGeneratedHeader(); */ -struct TestStruct : public JSONSerializable { +struct TestStruct : public JsonSerializable { int someInt = 0; string someString = "foo"; string yetAnotherString = "bar"; }; /*! - * \brief The NestedTestStruct struct inherits from JSONSerializable and should hence have functional fromJson() + * \brief The NestedTestStruct struct inherits from JsonSerializable and should hence have functional fromJson() * and toJson() methods. This is asserted in OverallTests::testNesting(); */ -struct NestedTestStruct : public JSONSerializable { +struct NestedTestStruct : public JsonSerializable { list> nested; deque deq; }; /*! - * \brief The AnotherTestStruct struct inherits from JSONSerializable and should hence have functional fromJson() + * \brief The AnotherTestStruct struct inherits from JsonSerializable and should hence have functional fromJson() * and toJson() methods. This is asserted in OverallTests::testInheritence(); */ -struct AnotherTestStruct : public JSONSerializable { +struct AnotherTestStruct : public JsonSerializable { vector arrayOfStrings{ "a", "b", "cd" }; }; /*! - * \brief The DerivedTestStruct struct inherits from JSONSerializable and should hence have functional fromJson() + * \brief The DerivedTestStruct struct inherits from JsonSerializable and should hence have functional fromJson() * and toJson() methods. This is asserted in OverallTests::testInheritence(); */ -struct DerivedTestStruct : public TestStruct, public JSONSerializable { +struct DerivedTestStruct : public TestStruct, public JsonSerializable { bool someBool = true; }; @@ -54,13 +54,13 @@ struct NonSerializable { }; /*! - * \brief The MultipleDerivedTestStruct struct inherits from JSONSerializable and should hence have functional fromJson() + * \brief The MultipleDerivedTestStruct struct inherits from JsonSerializable and should hence have functional fromJson() * and toJson() methods. This is asserted in OverallTests::testInheritence(); */ struct MultipleDerivedTestStruct : public TestStruct, public AnotherTestStruct, public NonSerializable, - public JSONSerializable { + public JsonSerializable { bool someBool = false; }; diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index d035267..3d92426 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -5,9 +5,10 @@ set(META_PROJECT_TYPE library) # add project files set(HEADER_FILES - jsonreflector.h - jsonreflector-boosthana.h - jsonserializable.h + json/reflector.h + json/reflector-boosthana.h + json/serializable.h + json/errorhandling.h ) set(SRC_FILES ) diff --git a/lib/json/errorhandling.h b/lib/json/errorhandling.h new file mode 100644 index 0000000..620ab8b --- /dev/null +++ b/lib/json/errorhandling.h @@ -0,0 +1,190 @@ +#ifndef REFLECTIVE_RAPIDJSON_JSON_ERROR_HANDLING_H +#define REFLECTIVE_RAPIDJSON_JSON_ERROR_HANDLING_H + +/*! + * \file errorhandling.h + * \brief Contains helper for error handling when deserializing JSON files. + */ + +#include +#include + +#include + +#include +#include +#include + +namespace ReflectiveRapidJSON { + +/*! + * \brief The JsonDeserializationErrorKind enum specifies which kind of error happend when populating variables from parsing results. + */ +enum class JsonDeserializationErrorKind : byte { + TypeMismatch, +}; + +/*! + * \brief The JsonType enum specifies the JSON data type. + * \remarks This is currently only used for error handling to propagate expected and actual types in case of a mismatch. + */ +enum class JsonType : byte { + Null, + Number, + Bool, + String, + Array, + Object, +}; + +template >, Traits::Any, std::is_floating_point>>...> +constexpr JsonType jsonType() +{ + return JsonType::Number; +} + +template >...> constexpr JsonType jsonType() +{ + return JsonType::Bool; +} + +template , Traits::IsCString>...> constexpr JsonType jsonType() +{ + return JsonType::String; +} + +template , Traits::Not>>...> constexpr JsonType jsonType() +{ + return JsonType::Array; +} + +template , std::is_floating_point, Traits::IsString, Traits::IsCString, + Traits::IsIteratable>...> +constexpr JsonType jsonType() +{ + return JsonType::Object; +} + +/*! + * \brief Maps the type info provided by RapidJSON to JsonType. + */ +constexpr JsonType jsonType(RAPIDJSON_NAMESPACE::Type type) +{ + switch (type) { + case RAPIDJSON_NAMESPACE::kNullType: + return JsonType::Null; + case RAPIDJSON_NAMESPACE::kFalseType: + case RAPIDJSON_NAMESPACE::kTrueType: + return JsonType::Bool; + case RAPIDJSON_NAMESPACE::kObjectType: + return JsonType::Object; + case RAPIDJSON_NAMESPACE::kArrayType: + return JsonType::Array; + case RAPIDJSON_NAMESPACE::kStringType: + return JsonType::String; + case RAPIDJSON_NAMESPACE::kNumberType: + return JsonType::Number; + default: + return JsonType::Null; + } +} + +/*! + * \brief The JsonDeserializationError struct describes any errors of fromJson() except such caused by invalid JSON. + */ +struct JsonDeserializationError { + JsonDeserializationError(JsonDeserializationErrorKind kind, JsonType expectedType, JsonType actualType, const char *record, + const char *member = nullptr, std::size_t index = noIndex); + + /// \brief Which kind of error occured. + JsonDeserializationErrorKind kind; + /// \brief The expected type (might not be relevant for all error kinds). + JsonType expectedType; + /// \brief The actual type (might not be relevant for all error kinds). + JsonType actualType; + /// \brief The name of the class or struct which was being processed when the error was ascertained. + const char *record; + /// \brief The name of the member which was being processed when the error was ascertained. + const char *member; + /// \brief The index in the array which was being processed when the error was ascertained. + std::size_t index; + + /// \brief Indicates no array was being processed when the error occured. + static constexpr std::size_t noIndex = std::numeric_limits::max(); +}; + +/*! + * \brief Constructs a new JsonDeserializationError. + * \remarks Supposed to be called by JsonDeserializationErrors::reportTypeMismatch() and similar methods of JsonDeserializationErrors. + */ +inline JsonDeserializationError::JsonDeserializationError( + JsonDeserializationErrorKind kind, JsonType expectedType, JsonType actualType, const char *record, const char *member, std::size_t index) + : kind(kind) + , expectedType(expectedType) + , actualType(actualType) + , record(record) + , member(member) + , index(index) +{ +} + +/*! + * \brief The JsonDeserializationErrors struct can be passed to fromJson() for error handling. + * + * When passed to fromJson() and an error occurs, a JsonDeserializationError is added to this object. + * If throwOn is set, the JsonDeserializationError is additionally thrown making the error fatal. + * + * \remarks Errors due to invalid JSON always lead to a RAPIDJSON_NAMESPACE::ParseResult object being thrown. So this + * only concerns errors listed in JsonDeserializationErrorKind. + */ +struct JsonDeserializationErrors : public std::vector { + JsonDeserializationErrors(); + + template void reportTypeMismatch(RAPIDJSON_NAMESPACE::Type presentType); + + /// \brief The name of the class or struct which is currently being processed. + const char *currentRecord; + /// \brief The name of the member (in currentRecord) which is currently being processed. + const char *currentMember; + /// \brief The index in the array which is currently processed. + std::size_t currentIndex; + /// \brief The list of fatal error types in form of flags. + enum class ThrowOn : unsigned char { None = 0, TypeMismatch = 0x1 } throwOn; +}; + +/*! + * \brief Creates an empty JsonDeserializationErrors object with default context and no errors considered fatal. + */ +inline JsonDeserializationErrors::JsonDeserializationErrors() + : currentRecord("[document]") + , currentMember(nullptr) + , currentIndex(JsonDeserializationError::noIndex) + , throwOn(ThrowOn::None) +{ +} + +/*! + * \brief Combines to ThrowOn values. + */ +constexpr JsonDeserializationErrors::ThrowOn operator|(JsonDeserializationErrors::ThrowOn lhs, JsonDeserializationErrors::ThrowOn rhs) +{ + return static_cast(static_cast(lhs) | static_cast(rhs)); +} + +/*! + * \brief Reports a type missmatch between \tparam ExpectedType and \a presentType within the current context. + */ +template inline void JsonDeserializationErrors::reportTypeMismatch(RAPIDJSON_NAMESPACE::Type presentType) +{ + emplace_back( + JsonDeserializationErrorKind::TypeMismatch, jsonType(), jsonType(presentType), currentRecord, currentMember, currentIndex); + if (static_cast(throwOn) & static_cast(ThrowOn::TypeMismatch)) { + throw back(); + } +} + +} // namespace ReflectiveRapidJSON + +#endif // REFLECTIVE_RAPIDJSON_JSON_REFLECTOR_H diff --git a/lib/jsonreflector-boosthana.h b/lib/json/reflector-boosthana.h similarity index 89% rename from lib/jsonreflector-boosthana.h rename to lib/json/reflector-boosthana.h index c56e7a4..df0467e 100644 --- a/lib/jsonreflector-boosthana.h +++ b/lib/json/reflector-boosthana.h @@ -2,7 +2,7 @@ #define REFLECTIVE_RAPIDJSON_JSON_REFLECTOR_BOOST_HANA_H /*! - * \file jsonreflector-boosthana.h + * \file reflector-boosthana.h * \brief Contains generic functions relying on Boost.Hana which can replace the code which would * otherwise had to be generated. * \remarks @@ -12,7 +12,7 @@ * modifying the actual object. */ -#include "./jsonreflector.h" +#include "./reflector.h" // TODO: find out which header files are actually relevant rather than including the master #include @@ -37,7 +37,8 @@ void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value::Object &value, RA template , std::is_floating_point, std::is_pointer, Traits::All, Traits::Not>>>...> -void pull(Type &reflectable, RAPIDJSON_NAMESPACE::GenericValue>::ValueIterator &value, JSONParseErrors *errors) +void pull( + Type &reflectable, RAPIDJSON_NAMESPACE::GenericValue>::ValueIterator &value, JsonDeserializationErrors *errors) { boost::hana::for_each(boost::hana::keys(reflectable), [&reflectable, &value, &errors](auto key) { pull(boost::hana::at_key(reflectable, key), boost::hana::to(key), value, errors); @@ -47,7 +48,8 @@ void pull(Type &reflectable, RAPIDJSON_NAMESPACE::GenericValue, std::is_floating_point, std::is_pointer, Traits::All, Traits::Not>>>...> -void pull(Type &reflectable, const RAPIDJSON_NAMESPACE::GenericValue>::ConstObject &value, JSONParseErrors *errors) +void pull(Type &reflectable, const RAPIDJSON_NAMESPACE::GenericValue>::ConstObject &value, + JsonDeserializationErrors *errors) { boost::hana::for_each(boost::hana::keys(reflectable), [&reflectable, &value, &errors](auto key) { pull(boost::hana::at_key(reflectable, key), boost::hana::to(key), value, errors); diff --git a/lib/jsonreflector.h b/lib/json/reflector.h similarity index 67% rename from lib/jsonreflector.h rename to lib/json/reflector.h index a0ab8b0..dad5305 100644 --- a/lib/jsonreflector.h +++ b/lib/json/reflector.h @@ -2,7 +2,7 @@ #define REFLECTIVE_RAPIDJSON_JSON_REFLECTOR_H /*! - * \file jsonreflector.h + * \file reflector.h * \brief Contains functions to (de)serialize basic types such as int, double, bool, std::string, * std::vector, ... with RapidJSON. */ @@ -11,185 +11,17 @@ #include #include -#include #include #include #include -#include #include -#include + +#include "./errorhandling.h" namespace ReflectiveRapidJSON { -template struct JSONSerializable; - -/*! - * \brief The JSONParseErrorKind enum specifies which kind of error happend when populating variables from parsing results. - */ -enum class JSONParseErrorKind : byte { - TypeMismatch, -}; - -/*! - * \brief The JSONType enum specifies the JSON data type. - * \remarks This is currently only used for error handling to propagate expected and actual types in case of a mismatch. - */ -enum class JSONType : byte { - Null, - Number, - Bool, - String, - Array, - Object, -}; - -template >, Traits::Any, std::is_floating_point>>...> -constexpr JSONType jsonType() -{ - return JSONType::Number; -} - -template >...> constexpr JSONType jsonType() -{ - return JSONType::Bool; -} - -template , Traits::IsCString>...> constexpr JSONType jsonType() -{ - return JSONType::String; -} - -template , Traits::Not>>...> constexpr JSONType jsonType() -{ - return JSONType::Array; -} - -template , std::is_floating_point, Traits::IsString, Traits::IsCString, - Traits::IsIteratable>...> -constexpr JSONType jsonType() -{ - return JSONType::Object; -} - -/*! - * \brief Maps the type info provided by RapidJSON to JSONType. - */ -constexpr JSONType jsonType(RAPIDJSON_NAMESPACE::Type type) -{ - switch (type) { - case RAPIDJSON_NAMESPACE::kNullType: - return JSONType::Null; - case RAPIDJSON_NAMESPACE::kFalseType: - case RAPIDJSON_NAMESPACE::kTrueType: - return JSONType::Bool; - case RAPIDJSON_NAMESPACE::kObjectType: - return JSONType::Object; - case RAPIDJSON_NAMESPACE::kArrayType: - return JSONType::Array; - case RAPIDJSON_NAMESPACE::kStringType: - return JSONType::String; - case RAPIDJSON_NAMESPACE::kNumberType: - return JSONType::Number; - default: - return JSONType::Null; - } -} - -/*! - * \brief The JSONParseError struct describes any errors of fromJson() except such caused by invalid JSON. - */ -struct JSONParseError { - JSONParseError(JSONParseErrorKind kind, JSONType expectedType, JSONType actualType, const char *record, const char *member = nullptr, - std::size_t index = noIndex); - - /// \brief Which kind of error occured. - JSONParseErrorKind kind; - /// \brief The expected type (might not be relevant for all error kinds). - JSONType expectedType; - /// \brief The actual type (might not be relevant for all error kinds). - JSONType actualType; - /// \brief The name of the class or struct which was being processed when the error was ascertained. - const char *record; - /// \brief The name of the member which was being processed when the error was ascertained. - const char *member; - /// \brief The index in the array which was being processed when the error was ascertained. - std::size_t index; - - /// \brief Indicates no array was being processed when the error occured. - static constexpr std::size_t noIndex = std::numeric_limits::max(); -}; - -/*! - * \brief Constructs a new JSONParseError. - * \remarks Supposed to be called by JSONParseErrors::reportTypeMismatch() and similar methods of JSONParseErrors. - */ -inline JSONParseError::JSONParseError( - JSONParseErrorKind kind, JSONType expectedType, JSONType actualType, const char *record, const char *member, std::size_t index) - : kind(kind) - , expectedType(expectedType) - , actualType(actualType) - , record(record) - , member(member) - , index(index) -{ -} - -/*! - * \brief The JSONParseErrors struct can be passed to fromJson() for error handling. - * - * When passed to fromJson() and an error occurs, a JSONParseError is added to this object. - * If throwOn is set, the JSONParseError is additionally thrown making the error fatal. - * - * \remarks Errors due to invalid JSON always lead to a RAPIDJSON_NAMESPACE::ParseResult object being thrown. So this - * only concerns errors listed in JSONParseErrorKind. - */ -struct JSONParseErrors : public std::vector { - JSONParseErrors(); - - template void reportTypeMismatch(RAPIDJSON_NAMESPACE::Type presentType); - - /// \brief The name of the class or struct which is currently being processed. - const char *currentRecord; - /// \brief The name of the member (in currentRecord) which is currently being processed. - const char *currentMember; - /// \brief The index in the array which is currently processed. - std::size_t currentIndex; - /// \brief The list of fatal error types in form of flags. - enum class ThrowOn : unsigned char { None = 0, TypeMismatch = 0x1 } throwOn; -}; - -/*! - * \brief Creates an empty JSONParseErrors object with default context and no errors considered fatal. - */ -inline JSONParseErrors::JSONParseErrors() - : currentRecord("[document]") - , currentMember(nullptr) - , currentIndex(JSONParseError::noIndex) - , throwOn(ThrowOn::None) -{ -} - -/*! - * \brief Combines to ThrowOn values. - */ -constexpr JSONParseErrors::ThrowOn operator|(JSONParseErrors::ThrowOn lhs, JSONParseErrors::ThrowOn rhs) -{ - return static_cast(static_cast(lhs) | static_cast(rhs)); -} - -/*! - * \brief Reports a type missmatch between \tparam ExpectedType and \a presentType within the current context. - */ -template inline void JSONParseErrors::reportTypeMismatch(RAPIDJSON_NAMESPACE::Type presentType) -{ - emplace_back(JSONParseErrorKind::TypeMismatch, jsonType(), jsonType(presentType), currentRecord, currentMember, currentIndex); - if (static_cast(throwOn) & static_cast(ThrowOn::TypeMismatch)) { - throw back(); - } -} +template struct JsonSerializable; inline RAPIDJSON_NAMESPACE::StringBuffer documentToString(RAPIDJSON_NAMESPACE::Document &document) { @@ -346,17 +178,19 @@ void push(const Type &reflectable, RAPIDJSON_NAMESPACE::Value::Array &value, RAP template , std::is_floating_point, std::is_pointer, Traits::All, Traits::Not>>>...> -void pull(Type &reflectable, RAPIDJSON_NAMESPACE::GenericValue>::ValueIterator &value, JSONParseErrors *errors); +void pull( + Type &reflectable, RAPIDJSON_NAMESPACE::GenericValue>::ValueIterator &value, JsonDeserializationErrors *errors); template , std::is_floating_point, std::is_pointer, Traits::All, Traits::Not>>>...> -void pull(Type &reflectable, const RAPIDJSON_NAMESPACE::GenericValue>::ConstObject &value, JSONParseErrors *errors); +void pull(Type &reflectable, const RAPIDJSON_NAMESPACE::GenericValue>::ConstObject &value, + JsonDeserializationErrors *errors); template , std::is_floating_point, std::is_pointer, Traits::All, Traits::Not>>>...> -void pull(Type &reflectable, const RAPIDJSON_NAMESPACE::GenericValue> &value, JSONParseErrors *errors) +void pull(Type &reflectable, const RAPIDJSON_NAMESPACE::GenericValue> &value, JsonDeserializationErrors *errors) { if (!value.IsObject()) { if (errors) { @@ -368,7 +202,8 @@ void pull(Type &reflectable, const RAPIDJSON_NAMESPACE::GenericValue, std::is_floating_point, std::is_pointer>...> -inline void pull(Type &reflectable, RAPIDJSON_NAMESPACE::GenericValue>::ValueIterator &value, JSONParseErrors *errors) +inline void pull( + Type &reflectable, RAPIDJSON_NAMESPACE::GenericValue>::ValueIterator &value, JsonDeserializationErrors *errors) { if (!value->Is()) { if (errors) { @@ -381,7 +216,8 @@ inline void pull(Type &reflectable, RAPIDJSON_NAMESPACE::GenericValue, std::is_floating_point, std::is_pointer>...> -inline void pull(Type &reflectable, const RAPIDJSON_NAMESPACE::GenericValue> &value, JSONParseErrors *errors) +inline void pull( + Type &reflectable, const RAPIDJSON_NAMESPACE::GenericValue> &value, JsonDeserializationErrors *errors) { if (!value.Is()) { if (errors) { @@ -393,8 +229,8 @@ inline void pull(Type &reflectable, const RAPIDJSON_NAMESPACE::GenericValue -inline void pull( - std::string &reflectable, RAPIDJSON_NAMESPACE::GenericValue>::ValueIterator &value, JSONParseErrors *errors) +inline void pull(std::string &reflectable, RAPIDJSON_NAMESPACE::GenericValue>::ValueIterator &value, + JsonDeserializationErrors *errors) { if (!value->IsString()) { if (errors) { @@ -408,7 +244,7 @@ inline void pull( template <> inline void pull( - std::string &reflectable, const RAPIDJSON_NAMESPACE::GenericValue> &value, JSONParseErrors *errors) + std::string &reflectable, const RAPIDJSON_NAMESPACE::GenericValue> &value, JsonDeserializationErrors *errors) { if (!value.IsString()) { if (errors) { @@ -420,12 +256,12 @@ inline void pull( } template , Traits::Not>>...> -void pull(Type &reflectable, rapidjson::GenericValue>::ConstArray array, JSONParseErrors *errors); +void pull(Type &reflectable, rapidjson::GenericValue>::ConstArray array, JsonDeserializationErrors *errors); template , Traits::Not>, Traits::Not>>...> -void pull(Type &reflectable, rapidjson::GenericValue>::ValueIterator &value, JSONParseErrors *errors) +void pull(Type &reflectable, rapidjson::GenericValue>::ValueIterator &value, JsonDeserializationErrors *errors) { if (!value->IsArray()) { if (errors) { @@ -439,7 +275,7 @@ void pull(Type &reflectable, rapidjson::GenericValue, Traits::IsReservable, Traits::Not>>...> -void pull(Type &reflectable, rapidjson::GenericValue>::ValueIterator &value, JSONParseErrors *errors) +void pull(Type &reflectable, rapidjson::GenericValue>::ValueIterator &value, JsonDeserializationErrors *errors) { if (!value->IsArray()) { if (errors) { @@ -456,7 +292,7 @@ void pull(Type &reflectable, rapidjson::GenericValue, Traits::Not>, Traits::Not>>...> -void pull(Type &reflectable, const rapidjson::GenericValue> &value, JSONParseErrors *errors) +void pull(Type &reflectable, const rapidjson::GenericValue> &value, JsonDeserializationErrors *errors) { if (!value.IsArray()) { if (errors) { @@ -469,7 +305,7 @@ void pull(Type &reflectable, const rapidjson::GenericValue, Traits::IsReservable, Traits::Not>>...> -void pull(Type &reflectable, const rapidjson::GenericValue> &value, JSONParseErrors *errors) +void pull(Type &reflectable, const rapidjson::GenericValue> &value, JsonDeserializationErrors *errors) { if (!value.IsArray()) { if (errors) { @@ -483,7 +319,7 @@ void pull(Type &reflectable, const rapidjson::GenericValue, Traits::Not>>...> -void pull(Type &reflectable, rapidjson::GenericValue>::ConstArray array, JSONParseErrors *errors) +void pull(Type &reflectable, rapidjson::GenericValue>::ConstArray array, JsonDeserializationErrors *errors) { // clear previous contents of the array reflectable.clear(); @@ -502,13 +338,13 @@ void pull(Type &reflectable, rapidjson::GenericValuecurrentIndex = JSONParseError::noIndex; + errors->currentIndex = JsonDeserializationError::noIndex; } } template -inline void pull( - Type &reflectable, const char *name, const rapidjson::GenericValue>::ConstObject &value, JSONParseErrors *errors) +inline void pull(Type &reflectable, const char *name, const rapidjson::GenericValue>::ConstObject &value, + JsonDeserializationErrors *errors) { // find member auto member = value.FindMember(name); @@ -534,7 +370,7 @@ inline void pull( // define functions providing high-level JSON serialization -template , Type>>...> +template , Type>>...> RAPIDJSON_NAMESPACE::StringBuffer toJson(const Type &reflectable) { RAPIDJSON_NAMESPACE::Document document(RAPIDJSON_NAMESPACE::kObjectType); @@ -568,8 +404,8 @@ template >.. // define functions providing high-level JSON deserialization -template , Type>>...> -Type fromJson(const char *json, std::size_t jsonSize, JSONParseErrors *errors = nullptr) +template , Type>>...> +Type fromJson(const char *json, std::size_t jsonSize, JsonDeserializationErrors *errors = nullptr) { RAPIDJSON_NAMESPACE::Document doc(parseDocumentFromString(json, jsonSize)); if (!doc.IsObject()) { @@ -585,7 +421,7 @@ Type fromJson(const char *json, std::size_t jsonSize, JSONParseErrors *errors = } template , std::is_floating_point>...> -Type fromJson(const char *json, std::size_t jsonSize, JSONParseErrors *errors) +Type fromJson(const char *json, std::size_t jsonSize, JsonDeserializationErrors *errors) { RAPIDJSON_NAMESPACE::Document doc(parseDocumentFromString(json, jsonSize)); if (!doc.Is()) { @@ -599,7 +435,7 @@ Type fromJson(const char *json, std::size_t jsonSize, JSONParseErrors *errors) } template >...> -Type fromJson(const char *json, std::size_t jsonSize, JSONParseErrors *errors) +Type fromJson(const char *json, std::size_t jsonSize, JsonDeserializationErrors *errors) { RAPIDJSON_NAMESPACE::Document doc(parseDocumentFromString(json, jsonSize)); if (!doc.IsString()) { diff --git a/lib/jsonserializable.h b/lib/json/serializable.h similarity index 59% rename from lib/jsonserializable.h rename to lib/json/serializable.h index 0c8c64c..eb946d6 100644 --- a/lib/jsonserializable.h +++ b/lib/json/serializable.h @@ -2,12 +2,12 @@ #define REFLECTIVE_RAPIDJSON_JSON_SERIALIZABLE_H /*! - * \file jsonserializable.h - * \brief Contains only the definiation of the JSONSerializable template class which makes the reflection + * \file serializable.h + * \brief Contains only the definiation of the JsonSerializable template class which makes the reflection * accessible. The actual implementation is found in jsonreflector.h and generated files. */ -#include "./jsonreflector.h" +#include "./reflector.h" #include @@ -16,26 +16,26 @@ namespace ReflectiveRapidJSON { /*! - * \brief The JSONSerializable class provides the CRTP-base for (de)serializable objects. + * \brief The JsonSerializable class provides the CRTP-base for (de)serializable objects. */ -template struct JSONSerializable { +template 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, JSONParseErrors *errors = nullptr); - static Type fromJson(const char *json, JSONParseErrors *errors = nullptr); - static Type fromJson(const std::string &json, JSONParseErrors *errors = nullptr); + static Type fromJson(const char *json, std::size_t jsonSize, JsonDeserializationErrors *errors = nullptr); + static Type fromJson(const char *json, JsonDeserializationErrors *errors = nullptr); + static Type fromJson(const std::string &json, JsonDeserializationErrors *errors = nullptr); - static constexpr const char *qualifiedName = "ReflectiveRapidJSON::JSONSerializable"; + static constexpr const char *qualifiedName = "ReflectiveRapidJSON::JsonSerializable"; }; /*! * \brief Pushes the object to the specified RapidJSON array. */ -template void JSONSerializable::push(RAPIDJSON_NAMESPACE::Value &container) +template void JsonSerializable::push(RAPIDJSON_NAMESPACE::Value &container) { return Reflector::push(*this, container); } @@ -43,7 +43,7 @@ template void JSONSerializable::push(RAPIDJSON_NAMESPACE:: /*! * \brief Pushes the object to the specified RapidJSON object as a member with the specified \a name. */ -template void JSONSerializable::push(RAPIDJSON_NAMESPACE::Value &container, const char *name) +template void JsonSerializable::push(RAPIDJSON_NAMESPACE::Value &container, const char *name) { return Reflector::push(*this, name, container); } @@ -52,7 +52,7 @@ template void JSONSerializable::push(RAPIDJSON_NAMESPACE:: * \brief Converts the object to its JSON representation. * \remarks To obtain a string from the returned buffer, just use its GetString() method. */ -template RAPIDJSON_NAMESPACE::StringBuffer JSONSerializable::toJson() const +template RAPIDJSON_NAMESPACE::StringBuffer JsonSerializable::toJson() const { return Reflector::toJson(static_cast(*this)); } @@ -60,7 +60,7 @@ template RAPIDJSON_NAMESPACE::StringBuffer JSONSerializable Type JSONSerializable::fromJson(const char *json, std::size_t jsonSize, JSONParseErrors *errors) +template Type JsonSerializable::fromJson(const char *json, std::size_t jsonSize, JsonDeserializationErrors *errors) { return Reflector::fromJson(json, jsonSize, errors); } @@ -68,7 +68,7 @@ template Type JSONSerializable::fromJson(const char *json, /*! * \brief Constructs a new object from the specified JSON. */ -template Type JSONSerializable::fromJson(const char *json, JSONParseErrors *errors) +template Type JsonSerializable::fromJson(const char *json, JsonDeserializationErrors *errors) { return Reflector::fromJson(json, std::strlen(json), errors); } @@ -76,7 +76,7 @@ template Type JSONSerializable::fromJson(const char *json, /*! * \brief Constructs a new object from the specified JSON. */ -template Type JSONSerializable::fromJson(const std::string &json, JSONParseErrors *errors) +template Type JsonSerializable::fromJson(const std::string &json, JsonDeserializationErrors *errors) { return Reflector::fromJson(json.data(), json.size(), errors); } @@ -84,18 +84,18 @@ template Type JSONSerializable::fromJson(const std::string /*! * \brief Helps to disambiguate when inheritance is used. */ -template , Type>>...> JSONSerializable &as(Type &serializable) +template , Type>>...> JsonSerializable &as(Type &serializable) { - return static_cast &>(serializable); + return static_cast &>(serializable); } /*! * \brief Helps to disambiguate when inheritance is used. */ -template , Type>>...> -const JSONSerializable &as(const Type &serializable) +template , Type>>...> +const JsonSerializable &as(const Type &serializable) { - return static_cast &>(serializable); + return static_cast &>(serializable); } } // namespace ReflectiveRapidJSON diff --git a/lib/reflectable.h b/lib/reflectable.h deleted file mode 100644 index f5527fc..0000000 --- a/lib/reflectable.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef REFLECTIVE_RAPIDJSON_REFLECTABLE_H -#define REFLECTIVE_RAPIDJSON_REFLECTABLE_H - -#include "./reflect.h" - -#include - -#include - -namespace ReflectiveRapidJSON { - -template 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); -}; - -template void JSONSerializable::push(RAPIDJSON_NAMESPACE::Value &container) -{ - return Reflector::push(*this, container); -} - -template void JSONSerializable::push(RAPIDJSON_NAMESPACE::Value &container, const char *name) -{ - return Reflector::push(*this, name, container); -} - -template RAPIDJSON_NAMESPACE::StringBuffer JSONSerializable::toJson() const -{ - return Reflector::toJson(static_cast(*this)); -} - -template Type JSONSerializable::fromJson(const char *json, std::size_t jsonSize) -{ - return Reflector::fromJson(json, jsonSize); -} - -template Type JSONSerializable::fromJson(const char *json) -{ - return Reflector::fromJson(json, std::strlen(json)); -} - -template Type JSONSerializable::fromJson(const std::string &json) -{ - return Reflector::fromJson(json.data(), json.size()); -} - -} // namespace ReflectiveRapidJSON - -#endif // REFLECTIVE_RAPIDJSON_REFLECTABLE_H diff --git a/lib/tests/jsonreflector-boosthana.cpp b/lib/tests/jsonreflector-boosthana.cpp index 4d700aa..75bfaf9 100644 --- a/lib/tests/jsonreflector-boosthana.cpp +++ b/lib/tests/jsonreflector-boosthana.cpp @@ -1,5 +1,5 @@ -#include "../jsonreflector-boosthana.h" -#include "../jsonserializable.h" +#include "../json/reflector-boosthana.h" +#include "../json/serializable.h" #include #include @@ -30,7 +30,7 @@ using namespace ReflectiveRapidJSON; /// \cond // define some structs for testing serialization -struct TestObjectHana : public JSONSerializable { +struct TestObjectHana : public JsonSerializable { //TestObjectHana(){}; //TestObjectHana(const TestObjectHana &) //{ @@ -39,11 +39,11 @@ struct TestObjectHana : public JSONSerializable { BOOST_HANA_DEFINE_STRUCT(TestObjectHana, (int, number), (double, number2), (vector, numbers), (string, text), (bool, boolean)); }; -struct NestingObjectHana : public JSONSerializable { +struct NestingObjectHana : public JsonSerializable { BOOST_HANA_DEFINE_STRUCT(NestingObjectHana, (string, name), (TestObjectHana, testObj)); }; -struct NestingArrayHana : public JSONSerializable { +struct NestingArrayHana : public JsonSerializable { BOOST_HANA_DEFINE_STRUCT(NestingArrayHana, (string, name), (vector, testObjects)); }; @@ -176,7 +176,7 @@ void JSONReflectorBoostHanaTests::testDeserializePrimitives() bool bool1 = false, bool2 = true; float float1 = 0.0; double double1 = 0.0; - JSONParseErrors errors; + JsonDeserializationErrors errors; Reflector::pull(str1, array, &errors); Reflector::pull(int1, array, &errors); Reflector::pull(float1, array, &errors); @@ -242,11 +242,11 @@ void JSONReflectorBoostHanaTests::testDeserializeNestedObjects() } /*! - * \brief Tests whether JSONParseError is thrown on type mismatch. + * \brief Tests whether JsonDeserializationError is thrown on type mismatch. */ void JSONReflectorBoostHanaTests::testHandlingTypeMismatch() { - JSONParseErrors errors; + JsonDeserializationErrors errors; NestingArrayHana::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}]}", @@ -257,9 +257,9 @@ void JSONReflectorBoostHanaTests::testHandlingTypeMismatch() "\"test\",\"boolean\":false}}", &errors); CPPUNIT_ASSERT_EQUAL(1_st, errors.size()); - CPPUNIT_ASSERT_EQUAL(JSONParseErrorKind::TypeMismatch, errors.front().kind); - CPPUNIT_ASSERT_EQUAL(JSONType::Number, errors.front().expectedType); - CPPUNIT_ASSERT_EQUAL(JSONType::String, errors.front().actualType); + CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors.front().kind); + CPPUNIT_ASSERT_EQUAL(JsonType::Number, errors.front().expectedType); + CPPUNIT_ASSERT_EQUAL(JsonType::String, errors.front().actualType); CPPUNIT_ASSERT_EQUAL("number"s, string(errors.front().member)); CPPUNIT_ASSERT_EQUAL("[document]"s, string(errors.front().record)); errors.clear(); @@ -268,23 +268,23 @@ void JSONReflectorBoostHanaTests::testHandlingTypeMismatch() "\"test\",\"boolean\":false}}", &errors); CPPUNIT_ASSERT_EQUAL(1_st, errors.size()); - CPPUNIT_ASSERT_EQUAL(JSONParseErrorKind::TypeMismatch, errors.front().kind); - CPPUNIT_ASSERT_EQUAL(JSONType::Array, errors.front().expectedType); - CPPUNIT_ASSERT_EQUAL(JSONType::Number, errors.front().actualType); + CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors.front().kind); + CPPUNIT_ASSERT_EQUAL(JsonType::Array, errors.front().expectedType); + CPPUNIT_ASSERT_EQUAL(JsonType::Number, errors.front().actualType); CPPUNIT_ASSERT_EQUAL("numbers"s, string(errors.front().member)); CPPUNIT_ASSERT_EQUAL("[document]"s, string(errors.front().record)); errors.clear(); NestingObjectHana::fromJson("{\"name\":[],\"testObj\":\"this is not an object\"}", &errors); CPPUNIT_ASSERT_EQUAL(2_st, errors.size()); - CPPUNIT_ASSERT_EQUAL(JSONParseErrorKind::TypeMismatch, errors.front().kind); - CPPUNIT_ASSERT_EQUAL(JSONType::String, errors.front().expectedType); - CPPUNIT_ASSERT_EQUAL(JSONType::Array, errors.front().actualType); + CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors.front().kind); + CPPUNIT_ASSERT_EQUAL(JsonType::String, errors.front().expectedType); + CPPUNIT_ASSERT_EQUAL(JsonType::Array, errors.front().actualType); CPPUNIT_ASSERT_EQUAL("name"s, string(errors.front().member)); CPPUNIT_ASSERT_EQUAL("[document]"s, string(errors.front().record)); - CPPUNIT_ASSERT_EQUAL(JSONParseErrorKind::TypeMismatch, errors.back().kind); - CPPUNIT_ASSERT_EQUAL(JSONType::Object, errors.back().expectedType); - CPPUNIT_ASSERT_EQUAL(JSONType::String, errors.back().actualType); + CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors.back().kind); + CPPUNIT_ASSERT_EQUAL(JsonType::Object, errors.back().expectedType); + CPPUNIT_ASSERT_EQUAL(JsonType::String, errors.back().actualType); CPPUNIT_ASSERT_EQUAL("testObj"s, string(errors.back().member)); CPPUNIT_ASSERT_EQUAL("[document]"s, string(errors.back().record)); errors.clear(); @@ -295,26 +295,26 @@ void JSONReflectorBoostHanaTests::testHandlingTypeMismatch() "141592653589793,\"numbers\":[1,2,3,4,\"bar\"],\"text\":\"test\",\"boolean\":false}]}", &errors)); CPPUNIT_ASSERT_EQUAL(3_st, errors.size()); - CPPUNIT_ASSERT_EQUAL(JSONParseErrorKind::TypeMismatch, errors[0].kind); - CPPUNIT_ASSERT_EQUAL(JSONType::Object, errors[0].expectedType); - CPPUNIT_ASSERT_EQUAL(JSONType::Number, errors[0].actualType); + CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors[0].kind); + CPPUNIT_ASSERT_EQUAL(JsonType::Object, errors[0].expectedType); + CPPUNIT_ASSERT_EQUAL(JsonType::Number, errors[0].actualType); CPPUNIT_ASSERT_EQUAL("testObjects"s, string(errors[0].member)); CPPUNIT_ASSERT_EQUAL("[document]"s, string(errors[0].record)); CPPUNIT_ASSERT_EQUAL(0_st, errors[0].index); - CPPUNIT_ASSERT_EQUAL(JSONParseErrorKind::TypeMismatch, errors[1].kind); - CPPUNIT_ASSERT_EQUAL(JSONType::Object, errors[1].expectedType); - CPPUNIT_ASSERT_EQUAL(JSONType::String, errors[1].actualType); + CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors[1].kind); + CPPUNIT_ASSERT_EQUAL(JsonType::Object, errors[1].expectedType); + CPPUNIT_ASSERT_EQUAL(JsonType::String, errors[1].actualType); CPPUNIT_ASSERT_EQUAL(2_st, errors[1].index); CPPUNIT_ASSERT_EQUAL("testObjects"s, string(errors[1].member)); CPPUNIT_ASSERT_EQUAL("[document]"s, string(errors[1].record)); - CPPUNIT_ASSERT_EQUAL(JSONParseErrorKind::TypeMismatch, errors[2].kind); - CPPUNIT_ASSERT_EQUAL(JSONType::Number, errors[2].expectedType); - CPPUNIT_ASSERT_EQUAL(JSONType::String, errors[2].actualType); + CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors[2].kind); + CPPUNIT_ASSERT_EQUAL(JsonType::Number, errors[2].expectedType); + CPPUNIT_ASSERT_EQUAL(JsonType::String, errors[2].actualType); CPPUNIT_ASSERT_EQUAL("numbers"s, string(errors[2].member)); CPPUNIT_ASSERT_EQUAL("[document]"s, string(errors[2].record)); CPPUNIT_ASSERT_EQUAL(4_st, errors[2].index); errors.clear(); - errors.throwOn = JSONParseErrors::ThrowOn::TypeMismatch; - CPPUNIT_ASSERT_THROW(NestingObjectHana::fromJson("{\"name\":[],\"testObj\":\"this is not an object\"}", &errors), JSONParseError); + errors.throwOn = JsonDeserializationErrors::ThrowOn::TypeMismatch; + CPPUNIT_ASSERT_THROW(NestingObjectHana::fromJson("{\"name\":[],\"testObj\":\"this is not an object\"}", &errors), JsonDeserializationError); } diff --git a/lib/tests/jsonreflector.cpp b/lib/tests/jsonreflector.cpp index 48abebe..472d1c9 100644 --- a/lib/tests/jsonreflector.cpp +++ b/lib/tests/jsonreflector.cpp @@ -1,5 +1,5 @@ -#include "../jsonreflector.h" -#include "../jsonserializable.h" +#include "../json/reflector.h" +#include "../json/serializable.h" #include #include @@ -30,7 +30,7 @@ using namespace ReflectiveRapidJSON; /// \cond // define some structs for testing serialization -struct TestObject : public JSONSerializable { +struct TestObject : public JsonSerializable { int number; double number2; vector numbers; @@ -38,12 +38,12 @@ struct TestObject : public JSONSerializable { bool boolean; }; -struct NestingObject : public JSONSerializable { +struct NestingObject : public JsonSerializable { string name; TestObject testObj; }; -struct NestingArray : public JSONSerializable { +struct NestingArray : public JsonSerializable { string name; vector testObjects; }; @@ -73,7 +73,8 @@ template <> inline void push(const NestingArray &reflectable, Valu push(reflectable.testObjects, "testObjects", value, allocator); } -template <> inline void pull(TestObject &reflectable, const GenericValue>::ConstObject &value, JSONParseErrors *errors) +template <> +inline void pull(TestObject &reflectable, const GenericValue>::ConstObject &value, JsonDeserializationErrors *errors) { const char *previousRecord; if (errors) { @@ -90,7 +91,8 @@ template <> inline void pull(TestObject &reflectable, const GenericV } } -template <> inline void pull(NestingObject &reflectable, const GenericValue>::ConstObject &value, JSONParseErrors *errors) +template <> +inline void pull(NestingObject &reflectable, const GenericValue>::ConstObject &value, JsonDeserializationErrors *errors) { const char *previousRecord; if (errors) { @@ -104,7 +106,8 @@ template <> inline void pull(NestingObject &reflectable, const Ge } } -template <> inline void pull(NestingArray &reflectable, const GenericValue>::ConstObject &value, JSONParseErrors *errors) +template <> +inline void pull(NestingArray &reflectable, const GenericValue>::ConstObject &value, JsonDeserializationErrors *errors) { const char *previousRecord; if (errors) { @@ -131,7 +134,6 @@ template <> inline void pull(NestingArray &reflectable, const Gene */ class JSONReflectorTests : public TestFixture { CPPUNIT_TEST_SUITE(JSONReflectorTests); - CPPUNIT_TEST(experiment); CPPUNIT_TEST(testSerializePrimitives); CPPUNIT_TEST(testSerializeSimpleObjects); CPPUNIT_TEST(testSerializeNestedObjects); @@ -169,33 +171,6 @@ void JSONReflectorTests::tearDown() { } -/*! - * \brief Not a real test, just some assertions for experimenting with the RapidJSON library. - */ -void JSONReflectorTests::experiment() -{ - Document doc(kArrayType); - Document::AllocatorType &alloc = doc.GetAllocator(); - - /* - doc.PushBack(25, alloc); - doc.PushBack(26, alloc); - doc.SetObject(); - doc.AddMember(StringRef("test"), 27, alloc); - - StringBuffer strbuf; - Writer jsonWriter(strbuf); - doc.Accept(jsonWriter); - */ - - doc.Parse("[\"a\", 5, \"test\", \"7\"]"); - GenericValue>::Array a = doc.GetArray(); - CPPUNIT_ASSERT_EQUAL("a"s, string(a[0].GetString())); - CPPUNIT_ASSERT_EQUAL(5, a[1].GetInt()); - //CPPUNIT_ASSERT_EQUAL(5, a[2].GetInt()); - //CPPUNIT_ASSERT_EQUAL(7, a[3].GetInt()); -} - /*! * \brief Tests serializing strings, numbers, arrays and boolean. */ @@ -283,7 +258,7 @@ void JSONReflectorTests::testDeserializePrimitives() bool bool1 = false, bool2 = true; float float1 = 0.0; double double1 = 0.0; - JSONParseErrors errors; + JsonDeserializationErrors errors; Reflector::pull(str1, array, &errors); Reflector::pull(int1, array, &errors); Reflector::pull(float1, array, &errors); @@ -363,11 +338,11 @@ void JSONReflectorTests::testHandlingParseError() } /*! - * \brief Tests whether JSONParseError is thrown on type mismatch. + * \brief Tests whether JsonDeserializationError is thrown on type mismatch. */ void JSONReflectorTests::testHandlingTypeMismatch() { - JSONParseErrors errors; + JsonDeserializationErrors errors; 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}]}", @@ -378,9 +353,9 @@ void JSONReflectorTests::testHandlingTypeMismatch() "\"test\",\"boolean\":false}}", &errors); CPPUNIT_ASSERT_EQUAL(1_st, errors.size()); - CPPUNIT_ASSERT_EQUAL(JSONParseErrorKind::TypeMismatch, errors.front().kind); - CPPUNIT_ASSERT_EQUAL(JSONType::Number, errors.front().expectedType); - CPPUNIT_ASSERT_EQUAL(JSONType::String, errors.front().actualType); + CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors.front().kind); + CPPUNIT_ASSERT_EQUAL(JsonType::Number, errors.front().expectedType); + CPPUNIT_ASSERT_EQUAL(JsonType::String, errors.front().actualType); CPPUNIT_ASSERT_EQUAL("number"s, string(errors.front().member)); CPPUNIT_ASSERT_EQUAL("TestObject"s, string(errors.front().record)); errors.clear(); @@ -389,23 +364,23 @@ void JSONReflectorTests::testHandlingTypeMismatch() "\"test\",\"boolean\":false}}", &errors); CPPUNIT_ASSERT_EQUAL(1_st, errors.size()); - CPPUNIT_ASSERT_EQUAL(JSONParseErrorKind::TypeMismatch, errors.front().kind); - CPPUNIT_ASSERT_EQUAL(JSONType::Array, errors.front().expectedType); - CPPUNIT_ASSERT_EQUAL(JSONType::Number, errors.front().actualType); + CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors.front().kind); + CPPUNIT_ASSERT_EQUAL(JsonType::Array, errors.front().expectedType); + CPPUNIT_ASSERT_EQUAL(JsonType::Number, errors.front().actualType); CPPUNIT_ASSERT_EQUAL("numbers"s, string(errors.front().member)); CPPUNIT_ASSERT_EQUAL("TestObject"s, string(errors.front().record)); errors.clear(); NestingObject::fromJson("{\"name\":[],\"testObj\":\"this is not an object\"}", &errors); CPPUNIT_ASSERT_EQUAL(2_st, errors.size()); - CPPUNIT_ASSERT_EQUAL(JSONParseErrorKind::TypeMismatch, errors.front().kind); - CPPUNIT_ASSERT_EQUAL(JSONType::String, errors.front().expectedType); - CPPUNIT_ASSERT_EQUAL(JSONType::Array, errors.front().actualType); + CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors.front().kind); + CPPUNIT_ASSERT_EQUAL(JsonType::String, errors.front().expectedType); + CPPUNIT_ASSERT_EQUAL(JsonType::Array, errors.front().actualType); CPPUNIT_ASSERT_EQUAL("name"s, string(errors.front().member)); CPPUNIT_ASSERT_EQUAL("NestingObject"s, string(errors.front().record)); - CPPUNIT_ASSERT_EQUAL(JSONParseErrorKind::TypeMismatch, errors.back().kind); - CPPUNIT_ASSERT_EQUAL(JSONType::Object, errors.back().expectedType); - CPPUNIT_ASSERT_EQUAL(JSONType::String, errors.back().actualType); + CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors.back().kind); + CPPUNIT_ASSERT_EQUAL(JsonType::Object, errors.back().expectedType); + CPPUNIT_ASSERT_EQUAL(JsonType::String, errors.back().actualType); CPPUNIT_ASSERT_EQUAL("testObj"s, string(errors.back().member)); CPPUNIT_ASSERT_EQUAL("NestingObject"s, string(errors.back().record)); errors.clear(); @@ -416,26 +391,26 @@ void JSONReflectorTests::testHandlingTypeMismatch() "141592653589793,\"numbers\":[1,2,3,4,\"bar\"],\"text\":\"test\",\"boolean\":false}]}", &errors)); CPPUNIT_ASSERT_EQUAL(3_st, errors.size()); - CPPUNIT_ASSERT_EQUAL(JSONParseErrorKind::TypeMismatch, errors[0].kind); - CPPUNIT_ASSERT_EQUAL(JSONType::Object, errors[0].expectedType); - CPPUNIT_ASSERT_EQUAL(JSONType::Number, errors[0].actualType); + CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors[0].kind); + CPPUNIT_ASSERT_EQUAL(JsonType::Object, errors[0].expectedType); + CPPUNIT_ASSERT_EQUAL(JsonType::Number, errors[0].actualType); CPPUNIT_ASSERT_EQUAL("testObjects"s, string(errors[0].member)); CPPUNIT_ASSERT_EQUAL("NestingArray"s, string(errors[0].record)); CPPUNIT_ASSERT_EQUAL(0_st, errors[0].index); - CPPUNIT_ASSERT_EQUAL(JSONParseErrorKind::TypeMismatch, errors[1].kind); - CPPUNIT_ASSERT_EQUAL(JSONType::Object, errors[1].expectedType); - CPPUNIT_ASSERT_EQUAL(JSONType::String, errors[1].actualType); + CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors[1].kind); + CPPUNIT_ASSERT_EQUAL(JsonType::Object, errors[1].expectedType); + CPPUNIT_ASSERT_EQUAL(JsonType::String, errors[1].actualType); CPPUNIT_ASSERT_EQUAL(2_st, errors[1].index); CPPUNIT_ASSERT_EQUAL("testObjects"s, string(errors[1].member)); CPPUNIT_ASSERT_EQUAL("NestingArray"s, string(errors[1].record)); - CPPUNIT_ASSERT_EQUAL(JSONParseErrorKind::TypeMismatch, errors[2].kind); - CPPUNIT_ASSERT_EQUAL(JSONType::Number, errors[2].expectedType); - CPPUNIT_ASSERT_EQUAL(JSONType::String, errors[2].actualType); + CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors[2].kind); + CPPUNIT_ASSERT_EQUAL(JsonType::Number, errors[2].expectedType); + CPPUNIT_ASSERT_EQUAL(JsonType::String, errors[2].actualType); CPPUNIT_ASSERT_EQUAL("numbers"s, string(errors[2].member)); CPPUNIT_ASSERT_EQUAL("TestObject"s, string(errors[2].record)); CPPUNIT_ASSERT_EQUAL(4_st, errors[2].index); errors.clear(); - errors.throwOn = JSONParseErrors::ThrowOn::TypeMismatch; - CPPUNIT_ASSERT_THROW(NestingObject::fromJson("{\"name\":[],\"testObj\":\"this is not an object\"}", &errors), JSONParseError); + errors.throwOn = JsonDeserializationErrors::ThrowOn::TypeMismatch; + CPPUNIT_ASSERT_THROW(NestingObject::fromJson("{\"name\":[],\"testObj\":\"this is not an object\"}", &errors), JsonDeserializationError); }