SC::SerializationJson reads or writes C++ structures to / from json using Reflection information.
Let's consider the following structure described by Reflection:
struct SC::Test
{
int x = 2;
float y = 1.5f;
int xy[2] = {1, 3};
String myTest = "asdf"_a8;
Vector<String> myVector = {"Str1"_a8, "Str2"_a8};
bool operator==(const Test& other) const
{
return x == other.x and y == other.y and
xy[0] == other.xy[0] and xy[1] == other.xy[1] and
myTest == other.myTest and myVector.size() == 2 and
myVector.size() == other.myVector.size() and
myVector[0] == other.myVector[0] and myVector[1] == other.myVector[1];
}
};
SC_REFLECT_STRUCT_VISIT(SC::Test)
SC_REFLECT_STRUCT_FIELD(0, x)
SC_REFLECT_STRUCT_FIELD(1, y)
SC_REFLECT_STRUCT_FIELD(2, xy)
SC_REFLECT_STRUCT_FIELD(3, myTest)
SC_REFLECT_STRUCT_FIELD(4, myVector)
SC_REFLECT_STRUCT_LEAVE()
This is how you can serialize the class to JSON
constexpr StringView testJSON = R"({"x":2,"y":1.50,"xy":[1,3],"myTest":"asdf","myVector":["Str1","Str2"]})"_a8;
Test test;
SmallBuffer<256> buffer;
StringFormatOutput output(StringEncoding::Ascii, buffer);
const StringView serializedJSON({buffer.data(), buffer.size() - 1}, false, StringEncoding::Ascii);
This is how you can de-serialize the class from JSON, matching fields by their label name, even if they come in different order than the original class or even if there are missing field.
constexpr StringView scrambledJson =
R"({"y" : 1.50, "x": 2.0, "myVector" : ["Str1","Str2"], "myTest":"asdf"})"_a8;
Test test;
test.x = 0;
test.y = 0;
(void)test.myVector.resize(1);
(void)test.myTest.assign("FDFSA"_a8);
SC_TEST_EXPECT(SerializationJson::loadVersioned(test, scrambledJson));
This is a special loader to deserialize the class from the exact same JSON that was output by the serializer itself. Whitespace changes are fine, but changing the order in which two fields exists or removing one will make deserialization fail. If these limitations are fine for the usage (for example the generated json files are not meant to be manually edited by users) than maybe it could be worth using it, as this code path is a lot simpler (*) than SC::SerializationJson::loadVersioned.
constexpr StringView testJSON = R"({"x":2,"y":1.50,"xy":[1,3],"myTest":"asdf","myVector":["Str1","Str2"]})"_a8;
Test test;
test.x = 1;
test.y = 3.22f;
test.xy[0] = 4;
test.xy[1] = 4;
test.myTest = "KFDOK";
test.myVector = {"LPDFSOK", "DSAFKO"};
- Note
- (*) simpler code probably means faster code, even if it has not been properly benchmarked yet so the hypothetical performance gain is yet to be defined.