RReverser / serde-xml-rs

xml-rs based deserializer for Serde (compatible with 1.0+)
https://crates.io/crates/serde-xml-rs
MIT License
269 stars 90 forks source link

Fix Vec<Struct> seralization #186 #187

Closed burleight closed 1 year ago

burleight commented 1 year ago

Fixes a bug where open_tag wasn't being for each struct in the sequence.

Addresses #186

rrichardson commented 1 year ago

This seems to fix some things, but I think there still might be a more fundamental error in the algorithm.

for example:

pub struct Delete {
    pub objects: ObjectIdentifierList,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub quiet: Option<Quiet>,
}

pub struct ObjectIdentifier {
    pub key: ObjectKey,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub version_id: Option<ObjectVersionId>,
}

pub struct ObjectKey (String);

pub type ObjectIdentifierList = Vec<ObjectIdentifier>;

produces this:

<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<Delete>
    <Objects>
        <ObjectIdentifier>
            <Key>maWd5TyizQZd</Key>
            <VersionId>WIANrW0Tg88KS</VersionId>
        </ObjectIdentifier>
    </Objects>
    <VersionId>
        <ObjectIdentifier>
            <Key>l2jvYR5rMYGe</Key>
        </ObjectIdentifier>
    </VersionId>
    <Key>
        <ObjectIdentifier>
            <Key>QgaJMIWJBp</Key>
        </ObjectIdentifier>
    </Key>
    <Key>
        <ObjectIdentifier>
            <Key>lE7mT7WL1790</Key>
            <VersionId>BuRCzWrhJZclFbKSxO</VersionId>
        </ObjectIdentifier>
    </Key>
    <VersionId>
        <ObjectIdentifier>
            <Key>QaGqSREk</Key>
            <VersionId>mkZFh43IyBD5hG</VersionId>
        </ObjectIdentifier>
    </VersionId>
    <VersionId>
        <ObjectIdentifier>
            <Key>Y805NG7O</Key>
            <VersionId>N4NYLO0rrLhOOhMq</VersionId>
        </ObjectIdentifier>
    </VersionId>
    <VersionId>
        <ObjectIdentifier>
            <Key>ZChUyC6</Key>
            <VersionId>Xk1cBLFusqF</VersionId>
        </ObjectIdentifier>
    </VersionId>
    <VersionId>
        <ObjectIdentifier>
            <Key>Kqj1GjEPsbf9</Key>
        </ObjectIdentifier>
    </VersionId>
    <Key>
        <ObjectIdentifier>
            <Key>jaQF1Nnwh2DCByxN</Key>
            <VersionId>FqvSpF</VersionId>
        </ObjectIdentifier>
    </Key>
    <Quiet>false</Quiet>
</Delete> 
frenata commented 1 year ago

@rrichardson I'm getting similar results on a small project, where the inner structure is being serialized 'outwards', so to speak. I can confirm that @burleight 's fix prevents an error from being thrown, but it doesn't affect the output of serialization.

SeanEClarke commented 1 year ago

Do you have an approx date when this will be merged and released?

piaoger commented 1 year ago

Deserializer works fine and need more work on serializer ...

use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct Tag {
    #[serde(rename = "$value")]
    pub value: String,
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Item {
    pub name: String,
    pub source: String,

    #[serde(rename = "tag")]
    pub tag: Vec<Tag>,
}
 fn test() {
    let src = r#"
    <Item>
        <name>Banana</name>
        <tag>TA</tag>
        <tag>TB</tag>
        <source>Store</source>
        <tag>TB</tag>
    </Item>"#;

    let mut de = serde_xml_rs::Deserializer::new_from_reader(src.as_bytes())
        .non_contiguous_seq_elements(true);
    let item = Item::deserialize(&mut de).unwrap();

    // {"name":"Banana","source":"Store","tag":[{"$value":"TA"},{"$value":"TB"},{"$value":"TB"}]}
    println!("{}", serde_json::to_string(&item).unwrap());

    // `Err` value: Writer { source: LastElementNameNotAvailable }'
    let reserialized_item = serde_xml_rs::to_string(&item).unwrap();
    assert_eq!(src, reserialized_item);
}

Edit: try to do a local tweak but failed and try to use quickxml instead. It borrowed some ideas from serde-xml-rs.