Can I automatically serialize an object?
ArduinoJson users frequently ask if there is a way to serialize an object automatically.
Let’s say you defined a struct
that contains the configuration of your program, and you want to restore this object when the application starts.
If we look at JsonConfigFile.ino, we see that we have to write some code to convert the struct
to a JsonObject
. Isn’t there a simpler way?
We can do that in C#, Java, Python, JavaScript, etc. so it must be possible with ArduinoJson, right?
Unfortunately, no. It’s not possible to do that.
Let me explain why I cannot implement this feature, and why I don’t really miss it.
No reflection/introspection in C++
The main reason why we can’t automatically serialize an object is that C++ lacks the reflection feature that other languages have. Indeed, there is no facility in C++ that allows a program to enumerate the members of an object.
There are some workarounds out there, but there are not pretty:
If you try to implement one of these solutions, you’ll quickly realize that they require more effort than writing the original conversion code.
No standard container on Arduino
Even if I decide to go with a solution like RTTR, there is another road-block: Arduino doesn’t provide a standard container like std::vector
or std::list
. Therefore, we have no common way to represent a collection of objects.
Sure, some cores embed libstdc++, so std::vector
and std::list
are available on some platforms, but I could not write something portable.
Deserialization is non trivial
Admitting that automatic serialization was possible, you must also think of the reverse operation: deserialization. I invite you to write a deserialization function for a complex object. You’ll realize that there are several decisions that you’ll have to make:
- What if a member is missing?
- What if there is an extra member?
- What if a value has the wrong type?
- What if an array is too large?
- What if a value is out of range?
I don’t think a library can automatically make these decisions for you. Even if the library offered options to configure the behavior for each member, you’d end up with something more complex than the hand-written function.
Why I don’t miss the feature
I’ve worked a lot with C#, and I used NewtonSoft Json.NET a few times. Admittedly, the conversion from structs to JSON is convenient.
However, my experience showed that serializing structs directly encourages programmers to serialize the business objects, thereby coupling the serialization format to the business model. Even in C#, I used to add an extra layer of indirection between my business logic and my serialization code, to be sure I can change one without breaking the other. For example, it allowed my app to be backward compatible with old configuration files.
The code to glue the business model with the serialization structs is very similar to the code you write with ArduinoJson to fill the JsonDocument
. One has to write this code anyway, so why bother.