I think that what I'm trying to do is impossible, but wanted to get a second opinion.
I'm introducing Rust to the codebase at work, and I need to mirror our existing behaviour written in Python. I have a number of situations similar to the following, a struct populated from a json in our database:
#[derive(Serialize, Deserialize)]
struct Thing {
foo: String,
baz: String,
// ... 20 more fields
version: u16,
}
In our database, until thing.version >= 22
, the baz
field was named bar
. I need to be able to serialize and deserialize both older and newer records. What is the best way to do that?
As far as I can tell, serialize_with
allows modifying only the value, not the key. And the rename
attribute doesn't seem to allow conditionally renaming.
My current solution is a custom deserializer which deserializes to serde_json::Value
, then check the version, and rename bar
to baz
if needed (and similarly for serialization). The problem is that my custom deserializer defines fn deserialize
, so I can no longer derive Deserialize
due to the name clash. I don't want to manually write a deserializer for all the many fields in the struct, so I'm maintaining a ThingHelper
struct, identical to Thing
, deserialize my modified serde_json::Value
into a ThingHelper
, then construct a Thing
from the ThingHelper
. This a lot of boilerplate, and doesn't help in the already uphill battle to convince my company to adopt more Rust.
Is there a better approach? E.g. if there is some way to both derive a serializer, and also implement my own (on the same struct), and call the derived from my own, that would be great. If that isn't possible, does that sounds like an appropriate feature request?