From 1a3dfbea48334ba6bc87b53c422fb95c54fdc96f Mon Sep 17 00:00:00 2001 From: Joshua Scott Date: Sat, 15 Dec 2018 16:52:36 +0000 Subject: [PATCH] serialization: Implement saving via JsonSerializer --- include/ki/serialization/BinarySerializer.h | 37 +-- include/ki/serialization/JsonSerializer.h | 35 +++ src/serialization/BinarySerializer.cpp | 123 ++++---- src/serialization/CMakeLists.txt | 1 + src/serialization/JsonSerializer.cpp | 105 +++++++ .../file.bin} | Bin test/samples/serialization/file.json | 285 ++++++++++++++++++ .../file_compressed.bin} | Bin .../regular.bin} | Bin test/samples/serialization/regular.json | 1 + .../regular_compressed.bin} | Bin test/src/unit-serialization.cpp | 136 ++++++++- 12 files changed, 633 insertions(+), 90 deletions(-) create mode 100644 include/ki/serialization/JsonSerializer.h create mode 100644 src/serialization/JsonSerializer.cpp rename test/samples/{serialization_binary_file.bin => serialization/file.bin} (100%) create mode 100644 test/samples/serialization/file.json rename test/samples/{serialization_binary_file_compressed.bin => serialization/file_compressed.bin} (100%) rename test/samples/{serialization_binary_regular.bin => serialization/regular.bin} (100%) create mode 100644 test/samples/serialization/regular.json rename test/samples/{serialization_binary_regular_compressed.bin => serialization/regular_compressed.bin} (100%) diff --git a/include/ki/serialization/BinarySerializer.h b/include/ki/serialization/BinarySerializer.h index bbecc24..68c24e0 100644 --- a/include/ki/serialization/BinarySerializer.h +++ b/include/ki/serialization/BinarySerializer.h @@ -64,19 +64,7 @@ namespace serialization * @param object * @param stream */ - virtual void presave_object(const pclass::PropertyClass *object, BitStream &stream) const; - - /** - * @param object - * @param stream - */ - void save_object(const pclass::PropertyClass *object, BitStream &stream) const; - - /** - * @param prop - * @param stream - */ - void save_property(const pclass::IProperty &prop, BitStream &stream) const; + virtual bool presave_object(const pclass::PropertyClass *object, BitStream &stream) const; /** * Read an object header, and instantiate the necessary PropertyClass. @@ -85,19 +73,6 @@ namespace serialization */ virtual void preload_object( std::unique_ptr &dest, BitStream &stream) const; - - /** - * @param dest - * @param stream - */ - void load_object( - std::unique_ptr &dest, BitStream &stream) const; - - /** - * @param prop - * @param stream - */ - void load_property(pclass::IProperty &prop, BitStream &stream) const; private: const pclass::TypeSystem *m_type_system; @@ -105,6 +80,16 @@ namespace serialization flags m_flags; const pclass::PropertyClass *m_root_object; + + void save_object(const pclass::PropertyClass *object, BitStream &stream) const; + void save_property(const pclass::IProperty &prop, BitStream &stream) const; + void save_dynamic_property( + const pclass::IDynamicProperty &prop, BitStream &stream) const; + + void load_object( + std::unique_ptr &dest, BitStream &stream) const; + void load_property(pclass::IProperty &prop, BitStream &stream) const; + void load_dynamic_property(pclass::IDynamicProperty &prop, BitStream &stream) const; }; } } diff --git a/include/ki/serialization/JsonSerializer.h b/include/ki/serialization/JsonSerializer.h new file mode 100644 index 0000000..3a9e4ec --- /dev/null +++ b/include/ki/serialization/JsonSerializer.h @@ -0,0 +1,35 @@ +#pragma once +#include +#include +#include "ki/pclass/Property.h" +#include "ki/pclass/TypeSystem.h" + +namespace ki +{ +namespace serialization +{ + /** + * TODO: Documentation + */ + class JsonSerializer + { + static const int FILE_INDENT_VALUE = 2; + + public: + explicit JsonSerializer(pclass::TypeSystem &type_system, bool is_file); + virtual ~JsonSerializer() {} + + std::string save(const pclass::PropertyClass *object) const; + void load(std::unique_ptr &dest, const std::string &json_string) const; + + private: + pclass::TypeSystem *m_type_system; + bool m_is_file; + + virtual bool presave_object(nlohmann::json &j, const pclass::PropertyClass *object) const; + nlohmann::json save_object(const pclass::PropertyClass *object) const; + void save_property(nlohmann::json &j, const pclass::IProperty &prop) const; + void save_dynamic_property(nlohmann::json &j, const pclass::IDynamicProperty &prop) const; + }; +} +} diff --git a/src/serialization/BinarySerializer.cpp b/src/serialization/BinarySerializer.cpp index c5f1053..d03c6da 100644 --- a/src/serialization/BinarySerializer.cpp +++ b/src/serialization/BinarySerializer.cpp @@ -114,22 +114,20 @@ namespace serialization } } - void BinarySerializer::presave_object(const pclass::PropertyClass *object, BitStream &stream) const + bool BinarySerializer::presave_object(const pclass::PropertyClass *object, BitStream &stream) const { // If we have an object, write the type hash, otherwise, write NULL (0). if (object) stream.write(object->get_type().get_hash()); else stream.write(NULL); + return object != nullptr; } void BinarySerializer::save_object(const pclass::PropertyClass *object, BitStream &stream) const { // Write any object headers - presave_object(object, stream); - - // Make sure we have an object to write - if (!object) + if (!presave_object(object, stream)) return; // Remember where we started writing the object data @@ -179,39 +177,17 @@ namespace serialization } // Is the property dynamic? (holding more than one value) - auto &property_type = prop.get_type(); if (prop.is_dynamic()) { // Cast the property to a IDynamicProperty const auto &dynamic_property = dynamic_cast(prop); - - // Write the number of elements - stream.write(dynamic_property.get_element_count()); - - // Iterate through the elements - for (auto i = 0; i < dynamic_property.get_element_count(); i++) - { - // Is this a collection of pointers? - if (prop.is_pointer()) - { - // Is the property a collection of pointers to other objects? - if (property_type.get_kind() == pclass::Type::kind::CLASS) - // Write the value as a nested object - save_object(dynamic_property.get_object(i), stream); - else - // Write the value as normal (let the property deal with dereferencing) - dynamic_property.write_value_to(stream, i); - } - else - // If the value isn't a pointer, and it's not dynamic, just write it as a value - dynamic_property.write_value_to(stream, i); - } + save_dynamic_property(dynamic_property, stream); } else if (prop.is_pointer()) { // Does this property hold a pointer to another object? - if (property_type.get_kind() == pclass::Type::kind::CLASS) + if (prop.get_type().get_kind() == pclass::Type::kind::CLASS) // Write the value as a nested object save_object(prop.get_object(), stream); else @@ -236,6 +212,32 @@ namespace serialization } } + void BinarySerializer::save_dynamic_property( + const pclass::IDynamicProperty& prop, BitStream& stream) const + { + // Write the number of elements + stream.write(prop.get_element_count()); + + // Iterate through the elements + for (auto i = 0; i < prop.get_element_count(); i++) + { + // Is this a collection of pointers? + if (prop.is_pointer()) + { + // Is the property a collection of pointers to other objects? + if (prop.get_type().get_kind() == pclass::Type::kind::CLASS) + // Write the value as a nested object + save_object(prop.get_object(i), stream); + else + // Write the value as normal (let the property deal with dereferencing) + prop.write_value_to(stream, i); + } + else + // If the value isn't a pointer, and it's not dynamic, just write it as a value + prop.write_value_to(stream, i); + } + } + void BinarySerializer::load( std::unique_ptr &dest, BitStream &stream, const std::size_t size) @@ -378,43 +380,16 @@ namespace serialization void BinarySerializer::load_property(pclass::IProperty &prop, BitStream &stream) const { - auto &property_type = prop.get_type(); if (prop.is_dynamic()) { auto &dynamic_property = dynamic_cast(prop); - - // How many elements are there in this dynamic property? - const auto element_count = stream.read(); - dynamic_property.set_element_count(element_count); - - // Load each of the elements - for (uint16_t i = 0; i < element_count; i++) - { - // Is this a collection of pointers? - if (dynamic_property.is_pointer()) - { - // Is the property a collection of pointers to other objects? - if (property_type.get_kind() == pclass::Type::kind::CLASS) - { - // Read the object as a nested object - std::unique_ptr object = nullptr; - load_object(object, stream); - dynamic_property.set_object(object, i); - } - else - // Read the value as normal (let the property deal with dereferencing) - dynamic_property.read_value_from(stream, i); - } - else - // If the value isn't a pointer, and it's not dynamic, just read it as a value - dynamic_property.read_value_from(stream, i); - } + load_dynamic_property(dynamic_property, stream); } else if (prop.is_pointer()) { // Does this property hold a pointer to another object? - if (property_type.get_kind() == pclass::Type::kind::CLASS) + if (prop.get_type().get_kind() == pclass::Type::kind::CLASS) { // Read the object as a nested object std::unique_ptr object = nullptr; @@ -429,5 +404,37 @@ namespace serialization // If the value isn't a pointer, and it's not dynamic, just read it as a value prop.read_value_from(stream); } + + void BinarySerializer::load_dynamic_property( + pclass::IDynamicProperty& prop, BitStream& stream) const + { + // How many elements are there in this dynamic property? + const auto element_count = stream.read(); + prop.set_element_count(element_count); + + // Load each of the elements + for (uint16_t i = 0; i < element_count; i++) + { + // Is this a collection of pointers? + if (prop.is_pointer()) + { + // Is the property a collection of pointers to other objects? + if (prop.get_type().get_kind() == pclass::Type::kind::CLASS) + { + // Read the object as a nested object + std::unique_ptr object = nullptr; + load_object(object, stream); + prop.set_object(object, i); + } + else + // Read the value as normal (let the property deal with dereferencing) + prop.read_value_from(stream, i); + } + else + // If the value isn't a pointer, and it's not dynamic, just read it as a value + prop.read_value_from(stream, i); + } + } + } } diff --git a/src/serialization/CMakeLists.txt b/src/serialization/CMakeLists.txt index fd194c8..2ad21fd 100644 --- a/src/serialization/CMakeLists.txt +++ b/src/serialization/CMakeLists.txt @@ -1,4 +1,5 @@ target_sources(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/src/serialization/BinarySerializer.cpp + ${PROJECT_SOURCE_DIR}/src/serialization/JsonSerializer.cpp ) \ No newline at end of file diff --git a/src/serialization/JsonSerializer.cpp b/src/serialization/JsonSerializer.cpp new file mode 100644 index 0000000..ba2780e --- /dev/null +++ b/src/serialization/JsonSerializer.cpp @@ -0,0 +1,105 @@ +#include "ki/serialization/JsonSerializer.h" + +using namespace nlohmann; + +namespace ki +{ +namespace serialization +{ + JsonSerializer::JsonSerializer(pclass::TypeSystem& type_system, + const bool is_file) + { + m_type_system = &type_system; + m_is_file = is_file; + } + + std::string JsonSerializer::save(const pclass::PropertyClass* object) const + { + return save_object(object).dump( + m_is_file ? FILE_INDENT_VALUE : -1, + ' ', + true + ); + } + + bool JsonSerializer::presave_object(json& j, const pclass::PropertyClass* object) const + { + // Add the object's meta information + j["_pclass_meta"] = { + { "type_hash", object ? object->get_type().get_hash() : NULL } + }; + return object != nullptr; + } + + json JsonSerializer::save_object(const pclass::PropertyClass* object) const + { + json j; + if (!presave_object(j, object)) + return j; + + // Add the object's properties + auto &property_list = object->get_properties(); + for (auto it = property_list.begin(); + it != property_list.end(); ++it) + { + auto &prop = *it; + save_property(j, prop); + } + + return j; + } + + void JsonSerializer::save_property(json& j, + const pclass::IProperty &prop) const + { + if (prop.is_dynamic()) + { + // Cast the property to a IDynamicProperty + const auto &dynamic_property = + dynamic_cast(prop); + return save_dynamic_property(j, dynamic_property); + } + + if (prop.get_type().get_kind() == pclass::Type::kind::CLASS) + { + auto *other_object = prop.get_object(); + j[prop.get_name()] = save_object(other_object); + } + else + { + auto value = prop.get_value().dereference(); + j[prop.get_name()] = value.get(); + } + } + + void JsonSerializer::save_dynamic_property(json& j, + const pclass::IDynamicProperty &prop) const + { + json property_value; + + for (auto i = 0; i < prop.get_element_count(); ++i) + { + if (prop.get_type().get_kind() == pclass::Type::kind::CLASS) + { + auto *other_object = prop.get_object(i); + property_value.push_back(save_object(other_object)); + } + else + { + auto value = prop.get_value(i).dereference(); + property_value.push_back(value.get()); + } + } + + j[prop.get_name()] = property_value; + } + + void JsonSerializer::load(std::unique_ptr& dest, + const std::string& json_string) const + { + // TODO: JSON Deserialization + auto j = json::parse(json_string); + dest = nullptr; + } +} +} diff --git a/test/samples/serialization_binary_file.bin b/test/samples/serialization/file.bin similarity index 100% rename from test/samples/serialization_binary_file.bin rename to test/samples/serialization/file.bin diff --git a/test/samples/serialization/file.json b/test/samples/serialization/file.json new file mode 100644 index 0000000..a74d7a7 --- /dev/null +++ b/test/samples/serialization/file.json @@ -0,0 +1,285 @@ +{ + "_pclass_meta": { + "type_hash": 2069042008 + }, + "collection": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99 + ], + "float32": 3.1415927410125732, + "float64": 3.141592653589793, + "int16": 515, + "int24": 263430, + "int32": 117967114, + "int4": -6, + "int64": 796025588171149586, + "int8": 1, + "int_ptr": 52, + "not_null_object": { + "_pclass_meta": { + "type_hash": 1181435066 + }, + "m_kind": 1 + }, + "null_object": { + "_pclass_meta": { + "type_hash": 0 + } + }, + "objects": [ + { + "_pclass_meta": { + "type_hash": 1180894394 + }, + "extra_value": 10, + "m_kind": 2 + }, + { + "_pclass_meta": { + "type_hash": 1180943546 + }, + "m_kind": 3 + } + ], + "ptr_collection": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99 + ], + "string": "This is a test value", + "uint16": 515, + "uint24": 263430, + "uint32": 117967114, + "uint4": 5, + "uint64": 796025588171149586, + "uint8": 1, + "value_object": { + "_pclass_meta": { + "type_hash": 1180894394 + }, + "extra_value": 20, + "m_kind": 2 + }, + "vector3d": { + "x": 24.0, + "y": 61.0, + "z": 3.619999885559082 + }, + "wstring": [ + 84, + 104, + 105, + 115, + 32, + 105, + 115, + 32, + 97, + 32, + 116, + 101, + 115, + 116, + 32, + 118, + 97, + 108, + 117, + 101 + ] +} \ No newline at end of file diff --git a/test/samples/serialization_binary_file_compressed.bin b/test/samples/serialization/file_compressed.bin similarity index 100% rename from test/samples/serialization_binary_file_compressed.bin rename to test/samples/serialization/file_compressed.bin diff --git a/test/samples/serialization_binary_regular.bin b/test/samples/serialization/regular.bin similarity index 100% rename from test/samples/serialization_binary_regular.bin rename to test/samples/serialization/regular.bin diff --git a/test/samples/serialization/regular.json b/test/samples/serialization/regular.json new file mode 100644 index 0000000..df8ad02 --- /dev/null +++ b/test/samples/serialization/regular.json @@ -0,0 +1 @@ +{"_pclass_meta":{"type_hash":2069042008},"collection":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99],"float32":3.1415927410125732,"float64":3.141592653589793,"int16":515,"int24":263430,"int32":117967114,"int4":-6,"int64":796025588171149586,"int8":1,"int_ptr":52,"not_null_object":{"_pclass_meta":{"type_hash":1181435066},"m_kind":1},"null_object":{"_pclass_meta":{"type_hash":0}},"objects":[{"_pclass_meta":{"type_hash":1180894394},"extra_value":10,"m_kind":2},{"_pclass_meta":{"type_hash":1180943546},"m_kind":3}],"ptr_collection":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99],"string":"This is a test value","uint16":515,"uint24":263430,"uint32":117967114,"uint4":5,"uint64":796025588171149586,"uint8":1,"value_object":{"_pclass_meta":{"type_hash":1180894394},"extra_value":20,"m_kind":2},"vector3d":{"x":24.0,"y":61.0,"z":3.619999885559082},"wstring":[84,104,105,115,32,105,115,32,97,32,116,101,115,116,32,118,97,108,117,101]} \ No newline at end of file diff --git a/test/samples/serialization_binary_regular_compressed.bin b/test/samples/serialization/regular_compressed.bin similarity index 100% rename from test/samples/serialization_binary_regular_compressed.bin rename to test/samples/serialization/regular_compressed.bin diff --git a/test/src/unit-serialization.cpp b/test/src/unit-serialization.cpp index dce8f2b..542c687 100644 --- a/test/src/unit-serialization.cpp +++ b/test/src/unit-serialization.cpp @@ -9,6 +9,7 @@ #include #include #include "ki/util/unique.h" +#include "ki/serialization/JsonSerializer.h" using namespace ki; @@ -17,7 +18,11 @@ using namespace ki; */ struct Vector3D { - Vector3D( + // Allow json caster to access private members + friend pclass::detail::value_caster; + friend pclass::detail::value_caster; + + explicit Vector3D( const float x = 0.0f, const float y = 0.0f, const float z = 0.0f) @@ -95,6 +100,45 @@ namespace detail return Value::make_value(value); } }; + + /** + * value_caster specialization for casting Vector3D to json object. + */ + template <> + struct value_caster + : value_caster_impl + { + Value cast(const Value &value) const override + { + auto &vector = value.get(); + const nlohmann::json j = { + { "x", vector.m_x }, + { "y", vector.m_y }, + { "z", vector.m_z } + }; + return Value::make_value(j); + } + }; + + /** + * value_caster specialization for casting json object to Vector3D. + */ + template <> + struct value_caster + : value_caster_impl + { + Value cast(const Value &value) const override + { + auto &j = value.get(); + return Value::make_value( + Vector3D( + j["x"].get(), + j["y"].get(), + j["z"].get() + ) + ); + } + }; } } } @@ -276,6 +320,10 @@ void define_types() g_type_system->define_class("class NestedTestObjectA", nested_test_object); g_type_system->define_class("class NestedTestObjectB", nested_test_object); g_type_system->define_class("class TestObject"); + + pclass::ValueCaster::declare(); + pclass::ValueCaster::declare(); + g_types_defined = true; } @@ -407,7 +455,7 @@ void test_serializer( // Open the sample data std::ifstream sample( - "samples/serialization_binary" + file_suffix + ".bin", + "samples/serialization/" + file_suffix + ".bin", std::ios::binary ); REQUIRE(sample.is_open()); @@ -468,6 +516,67 @@ void test_serializer( delete[] sample_data; } +/** +* Conduct save/load tests with a BinarySerializer instance. +*/ +void test_serializer( + std::unique_ptr &test_object, + serialization::JsonSerializer &serializer, + const std::string &file_suffix) +{ + // Open the sample data + std::ifstream sample_file( + "samples/serialization/" + file_suffix + ".json", + std::ios::binary + ); + REQUIRE(sample_file.is_open()); + + // Load the sample data into a buffer + const auto begin = sample_file.tellg(); + sample_file.seekg(0, std::ios::end); + const auto end = sample_file.tellg(); + const size_t sample_size = end - begin; + sample_file.seekg(std::ios::beg); + auto *sample_data = new char[sample_size]; + sample_file.read(sample_data, sample_size); + sample_file.close(); + + // Load the sample data into a string + const auto sample = std::string(sample_data, sample_size); + delete[] sample_data; + + SECTION("Saving objects") + { + // Create a test object, configure it, and write it to our stream + test_object = g_type_system->instantiate("class TestObject"); + configure_test_object(*test_object); + const auto json_string = serializer.save(test_object.get()); + + // Delete the test object here so that it is not + // unnecessarily validated by the caller + test_object = nullptr; + + // Validate the JSON string + REQUIRE(json_string == sample); + } + + SECTION("Loading objects") + { + // Load an object from the sample + std::unique_ptr object = nullptr; + serializer.load(object, sample); + + // Set test_object so that it is validated by the caller + /* + REQUIRE(object != nullptr); + test_object = std::unique_ptr( + dynamic_cast(object.release()) + ); + REQUIRE(test_object != nullptr); + */ + } +} + TEST_CASE("Serialization tests", "[serialization]") { std::unique_ptr test_object = nullptr; @@ -481,7 +590,7 @@ TEST_CASE("Serialization tests", "[serialization]") *g_type_system.get(), false, serialization::BinarySerializer::flags::NONE ); - test_serializer(test_object, serializer, "_regular"); + test_serializer(test_object, serializer, "regular"); } SECTION("File format without compression") { @@ -489,7 +598,7 @@ TEST_CASE("Serialization tests", "[serialization]") *g_type_system.get(), true, serialization::BinarySerializer::flags::WRITE_SERIALIZER_FLAGS ); - test_serializer(test_object, serializer, "_file"); + test_serializer(test_object, serializer, "file"); } SECTION("Regular format with compression") { @@ -497,7 +606,7 @@ TEST_CASE("Serialization tests", "[serialization]") *g_type_system.get(), false, serialization::BinarySerializer::flags::COMPRESSED ); - test_serializer(test_object, serializer, "_regular_compressed"); + test_serializer(test_object, serializer, "regular_compressed"); } SECTION("File format with compression") { @@ -506,7 +615,22 @@ TEST_CASE("Serialization tests", "[serialization]") serialization::BinarySerializer::flags::WRITE_SERIALIZER_FLAGS | serialization::BinarySerializer::flags::COMPRESSED ); - test_serializer(test_object, serializer, "_file_compressed"); + test_serializer(test_object, serializer, "file_compressed"); + } + } + + SECTION("JsonSerializer") + { + SECTION("Regular format") + { + serialization::JsonSerializer serializer(*g_type_system, false); + test_serializer(test_object, serializer, "regular"); + } + + SECTION("File format") + { + serialization::JsonSerializer serializer(*g_type_system, true); + test_serializer(test_object, serializer, "file"); } }