media-io / yaserde

Yet Another Serializer/Deserializer
MIT License
174 stars 58 forks source link

Structures with flatten are not deserialized correctly #179

Open roy-amelie opened 5 months ago

roy-amelie commented 5 months ago
#[derive(Debug, Default, Eq, PartialEq)]
pub struct Identifier(Uuid);

impl YaSerialize for Identifier {
    fn serialize<W: Write>(&self, writer: &mut ser::Serializer<W>) -> Result<(), String> {
        let urn = self.0.urn().to_string();
        let event = writer::XmlEvent::characters(&urn);
        let _ret = writer.write(event);
        Ok(())
    }

    fn serialize_attributes(
        &self,
        _attributes: Vec<OwnedAttribute>,
        namespace: Namespace,
    ) -> Result<(Vec<OwnedAttribute>, Namespace), String> {
        Ok((vec![], namespace))
    }
}

impl YaDeserialize for Identifier {
    fn deserialize<R: Read>(reader: &mut de::Deserializer<R>) -> Result<Self, String> {
        if let reader::XmlEvent::StartElement { .. } = reader.peek()?.to_owned() {
            let _ = reader.next_event();
            if let reader::XmlEvent::Characters(content) = reader.peek()?.to_owned() {
                return Uuid::parse_str(&content)
                    .map(Self)
                    .map_err(|msg| msg.to_string());
            }
        }
        Err("Bad Uuid element".to_owned())
    }
}

#[derive(Debug, Default, Eq, PartialEq, YaDeserialize, YaSerialize)]
pub struct Foo {
    #[yaserde(rename = "FooId")]
    foo_id: Identifier,
}

#[derive(Debug, Default, Eq, PartialEq, YaDeserialize, YaSerialize)]
pub struct Bar {
    #[yaserde(flatten)]
    foo: Foo,
    #[yaserde(rename = "BarId")]
    bar_id: Identifier,
}

let bar = r#"<?xml version="1.0" encoding="utf-8"?>
            <Bar>
                <FooId>urn:uuid:a78b9526-5ba8-46f9-a06f-561a9479bef8</FooId>
                <BarId>urn:uuid:a78b9526-5ba8-46f9-a06f-561a9479be52</BarId>
            </Bar>"#;

let bar: Bar = from_str(bar).unwrap();

let expected_bar = Bar {
    foo: Foo {
        foo_id: Identifier(
            Uuid::from_str("urn:uuid:a78b9526-5ba8-46f9-a06f-561a9479bef8").unwrap(),
        ),
    },
    bar_id: Identifier(
        Uuid::from_str("urn:uuid:a78b9526-5ba8-46f9-a06f-561a9479be52").unwrap(),
    ),
};

the result is

Bar { 
  foo: Foo { 
    foo_id: Identifier(00000000-0000-0000-0000-000000000000) 
  }, 
  bar_id: Identifier(a78b9526-5ba8-46f9-a06f-561a9479be52) }