How to use glaze to create a polymorphic object parser? #599
-
Hi there Thank you for your library, I'm checkig if I can use this library in a project. My approach is the following: Custom objects can be derived from that Serializable interface. A object handler takes all pointers to Serializable objects and parses them to a file. What is the problem now? How can I parse this structure back to my JsonArray and JsonObject types to be able to give the JsonObject's to my Serializable instances for loading? Is there a better way to achieve the goal of saving and loading custom objects in a polymorphic structure? Can I somhow create a custom data struct inside every derived class and parse that struct? Optimum solution would be if I can give the save function a type in which i can store the custom struct from that derived object. Thanks for any help and tips. Here is my test code:
The output of the console looks like this:
|
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 16 replies
-
looking into this |
Beta Was this translation helpful? Give feedback.
-
Hi @KROIA, If you use a std::variant, you'll eliminate most of your code.
Here is how you can write your objects: struct Obj1
{
int value;
std::string text;
};
struct Obj2
{
int value;
std::string text;
Obj1 obj1;
}; Now, we need to add some metadata to template <>
struct glz::meta<Obj1>
{
using T = Obj1;
static constexpr auto list_write = [](T& obj1) {
const auto& value = obj1.value;
return std::vector<int>{
value,
value + 1,
value + 2
};
};
static constexpr auto value = object(&T::value, &T::text, "list", glz::custom<skip{}, list_write>);
}; Now we can serialize/deserialize as you like using glaze functions: using Serializable = std::variant<Obj1, Obj2>;
std::vector<Serializable> objects{Obj1{1, "text 1"},
Obj1{2, "text 2"},
Obj2{3, "text 3", 10, "1000"},
Obj1{4, "text 4"},};
constexpr auto prettify = glz::opts{.prettify = true};
std::string data = glz::write<prettify>(objects); // writing
const auto is_error = glz::read_json(objects, data); // reading Here is my full test suite that I added to the unit tests: suite custom_object_variant_test = [] {
"custom_object_variant"_test = [] {
using Serializable = std::variant<Obj1, Obj2>;
std::vector<Serializable> objects{Obj1{1, "text 1"},
Obj1{2, "text 2"},
Obj2{3, "text 3", 10, "1000"},
Obj1{4, "text 4"},};
constexpr auto prettify = glz::opts{.prettify = true};
std::string data = glz::write<prettify>(objects);
expect(data == R"([
{
"value": 1,
"text": "text 1",
"list": [
1,
2,
3
]
},
{
"value": 2,
"text": "text 2",
"list": [
2,
3,
4
]
},
{
"value": 3,
"text": "text 3",
"obj1": {
"value": 10,
"text": "1000",
"list": [
10,
11,
12
]
}
},
{
"value": 4,
"text": "text 4",
"list": [
4,
5,
6
]
}
])");
objects.clear();
expect(!glz::read_json(objects, data));
expect(data == glz::write<prettify>(objects));
};
}; |
Beta Was this translation helpful? Give feedback.
@KROIA, you can also look at the
glz::json_t
generic type, which acts like your JsonArray and JsonObject. See generic-jsonThis comes with significant overhead, but will probably still be faster than QT's JSON, which has been benchmarked and is even slower than nlohmann JSON.