Using `flatten` and `rename="$value"` on adjacent fields causes error
I have an issue similar to this issue in serde-xml-rs.
I have the following implementation, where i use flatten and rename="$value" on fields in the same struct:
use serde::Deserialize;
use quick_xml::de;
#[derive(Debug, Deserialize)]
struct ParentStruct {
#[serde(flatten)]
flat_struct: FlatStruct,
#[serde(rename = "$value")]
children: Vec<ChildStruct>,
}
#[derive(Debug, Deserialize)]
struct FlatStruct {
a: String,
b: String,
}
#[derive(Debug, Deserialize)]
struct ChildStruct {
c: String,
d: String,
}
fn main() {
let xml = r##"
<ParentStruct a="1" b="2">
<ChildStruct c="3" d="4"/>
<ChildStruct c="5" d="6"/>
</ParentStruct>
"##;
let parent_struct: ParentStruct = de::from_str(xml).unwrap();
dbg!(parent_struct);
}
I expect to get a struct similar to:
ParentStruct {
flat_struct: FlatStruct {
a: "1",
b: "2",
},
children: [
ChildStruct {
c: "3",
d: "4",
},
ChildStruct {
c: "5",
d: "6",
},
],
}
But I get the following error:
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Custom("missing field `$value`")'
Using flatten or rename="$value" in isolation works perfectly, but the combination of the two seems to cause the error.
Is this a bug, or am I somehow using these macros wrong?
@askepen, actually, your example is working since merging #490 after few changes:
- attributes should have names started with
@ $valuespecial not is not required here
#[test]
fn issue326() {
#[derive(Debug, Deserialize, PartialEq)]
struct ParentStruct {
#[serde(flatten)]
flat_struct: FlatStruct,
#[serde(rename = "ChildStruct")]
children: Vec<ChildStruct>,
}
#[derive(Debug, Deserialize, PartialEq)]
struct FlatStruct {
#[serde(rename = "@a")]
a: String,
#[serde(rename = "@b")]
b: String,
}
#[derive(Debug, Deserialize, PartialEq)]
struct ChildStruct {
#[serde(rename = "@c")]
c: String,
#[serde(rename = "@d")]
d: String,
}
assert_eq!(
from_str::<ParentStruct>(
r#"
<ParentStruct a="1" b="2">
<ChildStruct c="3" d="4"/>
<ChildStruct c="5" d="6"/>
</ParentStruct>
"#
)
.unwrap(),
ParentStruct {
flat_struct: FlatStruct {
a: "1".to_string(),
b: "2".to_string(),
},
children: vec![
ChildStruct {
c: "3".to_string(),
d: "4".to_string(),
},
ChildStruct {
c: "5".to_string(),
d: "6".to_string(),
},
],
}
);
}
But I leave this bug open, because you spot a problem, that really exists:
#[test]
fn issue326_enum() {
#[derive(Debug, Deserialize, PartialEq)]
struct ParentStruct {
#[serde(flatten)]
flat_struct: FlatStruct,
#[serde(rename = "$value")]
children: Vec<Enum>,
}
#[derive(Debug, Deserialize, PartialEq)]
struct FlatStruct {
#[serde(rename = "@a")]
a: String,
#[serde(rename = "@b")]
b: String,
}
#[derive(Debug, Deserialize, PartialEq)]
enum Enum {
ChildStruct {
#[serde(rename = "@c")]
c: String,
#[serde(rename = "@d")]
d: String,
}
}
// Result:
// thread 'issue326_enum' panicked at 'called `Result::unwrap()` on an `Err` value: Custom("missing field `$value`")',
assert_eq!(
from_str::<ParentStruct>(
r#"
<ParentStruct a="1" b="2">
<ChildStruct c="3" d="4"/>
<ChildStruct c="5" d="6"/>
</ParentStruct>
"#
)
.unwrap(),
ParentStruct {
flat_struct: FlatStruct {
a: "1".to_string(),
b: "2".to_string(),
},
children: vec![
Enum::ChildStruct {
c: "3".to_string(),
d: "4".to_string(),
},
Enum::ChildStruct {
c: "5".to_string(),
d: "6".to_string(),
},
],
}
);
}
Problem disappeared after commenting out the flat_struct field. I don't known, although, if it would be possible to fix the issue on the quick-xml side. serde(flatten) issues usually due serde-rs/serde#1183