serde
serde copied to clipboard
Problem deserializing adjacently tagged enum with default content
I have an adjacently tagged enum, and I'd like for the content to be optional. The enum looks like:
#[derive(Deserialize, Debug)]
#[serde(tag = "tag", content = "content")]
enum TestEnum {
NoContent,
OptionalContent(#[serde(default)] OptionalContent),
}
#[derive(Deserialize, Default, Debug)]
struct OptionalContent {
_a: Option<String>,
}
I expected to be able to successfully deserialize the json {"tag": "OptionalContent"} into the OptionalContent variant and have the inner OptionalContent be populated with the default. The actual result was Err(Error("missing field content", line: 1, column: 26)).
When I change the input json to {"tag": "OptionalContent", "content": null}, I get a different error: Err(Error("invalid type: null, expected struct OptionalContent", line: 1, column: 42)).
I was able to get this to work is when the json is {"tag": "OptionalContent", "content": {}}, but I'd prefer to have the default work when content is either missing or null.
Is this a bug? Is there some other way to get this working? Appreciate whatever help or advice you're able to provide.
I believe that this does work if you use Option<OptionalContent>. However it would be nice if this worked automatically if the variant has a Default.
Related to #2248
Probably, this could be solving by allowing #[serde(default)] on enum variants in adjacently tagged enums. Then in case of absence of the content field corresponding variant should be constructed using Default implementation of all it's components:
#[derive(Deserialize, Debug)]
#[serde(tag = "tag", content = "content")]
// Also should be possible to specify enum attribute instead
// of specifying attribute on each variant
// #[serde(default)]
enum AdjacentlyTagged {
// result = Unit;
#[serde(default)]
Unit,
// result = Newtype1(MustImplementDefault::default());
#[serde(default)]
Newtype1(MustImplementDefault),
// result = Newtype2(d());
#[serde(default)]
Newtype2(#[serde(default = "d")] DoesNotImplementDefault),
// result = Tuple(MustImplementDefault::default(), d());
#[serde(default)]
Tuple(MustImplementDefault, #[serde(default = "d")] DoesNotImplementDefault),
// result = Struct { a: MustImplementDefault::default(), b: d() };
#[serde(default)]
Struct {
a: MustImplementDefault,
#[serde(default = "d")]
b: DoesNotImplementDefault,
},
}
Components should either implement Default, or have its own #[serde(default = "...")].