Serde is an amazing serialization library for Rust and has been a huge reason why I felt productive with it for years. However, already while at Sentry I got quite frustrated with some of the limitations with it but actually replacing Serde is tricky because of the might that it has in the ecosystem. Also because it's quite hard to actually do better without also making some potentially painful compromises.
Here are three examples of Serde corner cases that show poor interactions of Serde features or unexpected limitations: A number that is a map. An internally tagged enum, with serde_json's arbitrary_precision feature turned on. Flattening breaks integer keys.
Adapters do not compose. None of these are bugs that are easy to fix in Serde. They fall out of its design, and that design is protected by Serde's stability guarantees.
Back in 2022 I started an experiment called Deser. It's a serialization library for Rust that takes the user experience of Serde and puts it on top of a completely different architecture inspired by miniserde. I never really finished it and it sat around for a few years.
I picked it back up, and it has now reached a point where I think it's worth looking at. Even just to inspire others to see if they want to explore the space. The Name And Idea The name is Serde with its two halves swapped.
Deser is Serde but the other way around. In Serde, a type drives the deserialization process: a Deserialize impl asks the deserializer for the kind of value it expects, the format calls back into a visitor. Every nested value is handled by recursion which makes Serde deserialization inherently grow the stack with each level of nesting.
Deser on the other hand turns this around and the format tells the type of the next value and pushes events into a sink. When a sink hits the start of a nested value, it doesn't call into it but hands back a new sink to a driver, which keeps all state on the heap (in fact, in an arena). On the way out, emitters return their nested values instead of recursing into them.