serde-rs / serde

Serialization framework for Rust
https://serde.rs/
Apache License 2.0
9.16k stars 774 forks source link

Better message when failing to match any variant of an untagged enum #2157

Closed GeeWee closed 1 year ago

GeeWee commented 2 years ago

Reopen of issue #773 as there still seems to be interest, and there is someone who's started doing some work on it #1544 . Of ocurse, feel free to close, but I hope you'll reconsider this as important.

Further info: We have a lot of untagged enums in our public-facing API, and it's extremely difficult to give proper error messages to the user as all we can get out of Serde is data did not match any variant of untagged enum - if there was an opt-in to getting better error messages here, it would make our life a lot easier.

nirvana-msu commented 2 years ago

I think it is more common to encouter this than one might think. Many REST APIs are designed to give either some Ok response, or an error. This structure is best modelled with a top-level untagged enum - but it means that on deserialization failure, the error becomes completely meaningless, it does not explain anything at all. You then end up eyeballing hundreds of lines of pretty-printed JSON to find the discrepancy with your types.

There is another fork that has this baked in: jonasbb/serde but I'd much rather see this functionality in serde. I've tried to use both crates simultaneously (serde in the normal flow, and re-try with modified version on deserialization failure to extract a better message) - but while I can include both crates by renaming one of them, the use of proc macros makes it impossible to derive Deserialize correctly for the renamed crate. Yes, serde allows to customize crate name via an attribute - but I still cannot derive Deserialize from both crates at the same time. There is basically no reasonable workaround other completely switching to serde fork.

GeeWee commented 1 year ago

Related to #1544 which seems to have been stalled for a while.

dtolnay commented 1 year ago

I published https://docs.rs/serde-untagged implementing one of the suggested approaches from https://github.com/serde-rs/serde/pull/2376#issuecomment-1519172405. It constructs error messages by incorporating information about which of the Serde data model's types your type knows how to deserialize from. Also leading to better error messages is that you can avoid buffering (Content) when there is at most one map-based or seq-based variant.

If there are remaining use cases still not well served by this, I would like to see someone make a different crate dedicated to any of those.