can serialize but can't deserilize when combined `tag = ""` with `flatten`
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Package {
#[serde(default, flatten)]
pub kind: PackageType,
#[serde(default)]
pub var: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(tag = "kind", rename_all = "kebab-case", deny_unknown_fields)]
pub enum PackageType {
Local {},
Git(GitPkg),
}
impl Default for PackageType {
fn default() -> Self {
Self::Local {}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct GitPkg {
url: String,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let pkg = Package {
kind: PackageType::Local {},
var: "a".into(),
};
let json = serde_json::to_string_pretty(&pkg)?;
println!("{json}");
let pkg = serde_json::from_str::<Package>(&json)?;
dbg!(pkg);
Ok(())
}
This is the output:
{
"kind": "local",
"var": "a"
}
Error: Error("unknown field `kind`", line: 4, column: 1)
This error produced because of #[serde(deny_unknown_fields)] on Package. When this option is enabled and flatten fields are present, then content firstly buffered in FlatMapDeserializer. Then internally tagged enum deserialized from it using deserialize_any, which forwarded to deserialize_map
https://github.com/serde-rs/serde/blob/179954784683f35942ac2e1f076e0361b47f8178/serde/src/private/de.rs#L3249-L3258
which provides FlatMapAccess which does not consume data from the deserializer:
https://github.com/serde-rs/serde/blob/179954784683f35942ac2e1f076e0361b47f8178/serde/src/private/de.rs#L3358-L3374
Therefore, when it checks for the remaining fields, it sees those processed but not consumed fields.
Related: #1909.