serde icon indicating copy to clipboard operation
serde copied to clipboard

Allow deserializing adjacently tagged enum struct variants if all fields have #[serde(default)]

Open sciyoshi opened this issue 3 years ago • 2 comments

Suppose you have the following enum:

#[derive(Deserialize)]
#[serde(tag = "type", content = "attrs")]
enum Node {
     Doc { #[serde(default)] title: String }
}

(playground link)

The Doc variant of this enum can be constructed from empty content, i.e. when deserializing from {"type": "Doc", "attrs": {}}. In this case, it would be great if serde could also deserialize a value where the content is missing completely, i.e. {"type": "Doc"}.

This PR adds a check for struct-style variants where every field is marked with #[serde(default)].

See similar issue here: https://github.com/serde-rs/serde/issues/2233

sciyoshi avatar Oct 11 '22 03:10 sciyoshi

Is there anything else which needs to happen to push this over the line? I'm running into this at the moment; it looks like a fairly small change to have been sitting stale for a year.

To clarify for myself, would this allow e.g.


#[derive(Deserialize)]
#[serde(tag = "type", content = "attrs")]
enum Node {
     NeedsAttrs(SomeData),
     OptionalAttrs(#[serde(default)] OtherData),
}

struct SomeData {
    a: u8,
}

#[derive(Default)]
struct OtherData {}

i.e. it would be able to deserialise {"type": "OptionalAttrs"} even though not all variants have data implementing Default?

clbarnes avatar Oct 13 '23 11:10 clbarnes

@clbarnes yes, the PR as it stands should support deserializing from {"type": "OptionalAttrs"}. I'm not sure if this code still works as-is with the latest changes in main. Maybe @dtolnay can comment on whether this would be acceptable to merge?

sciyoshi avatar Jan 02 '24 16:01 sciyoshi