quick-xml icon indicating copy to clipboard operation
quick-xml copied to clipboard

Inconsistency with the use of name vs local_name in Serde deserialization implementation.

Open blankname opened this issue 4 years ago • 0 comments

use quick_xml::de::from_str;
use serde::Deserialize;

#[derive(Debug, Deserialize)]
struct Child {
}

#[derive(Debug, Deserialize)]
struct Parent {
  #[serde(rename = "child")]
  children: Vec<Child>
}

fn main() {
    let xml = r#"<parent xmlns:ns="http://example.org/namespace">
                  <child />
                  <ns:child />
                 </parent>"#;
    let p: Parent = from_str(xml).unwrap();
}

Gives the following error:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Custom("duplicate field `child`")', src/main.rs:19:21

If I understand correctly, this is because structs are being deserialized as maps using the MapAccess struct, which uses the element's local_name as the key.

So, for the purpose of mapping the child elements to the fields on the Parent struct they both have the same key.

However the SeqAccess struct, which is used to create the actual Vec<Child> doesn't use local_name.

This means that when SeqAccess gets to <ns:child/> it treats the element as having a different name than <child/> so it thinks the sequence has ended.

Control then returns back to MapAccess but MapAccess immediately tries mapping <ns:child /> to the same same field (children), which it's already filled so it treats it as a duplicate field.

Do you think it would be desirable to replace the use of name with local_name in the deserialization implementation?

blankname avatar May 15 '20 21:05 blankname