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

LastElementNameNotAvailable error on writing #186

Open rrichardson opened 1 year ago

rrichardson commented 1 year ago

When attempting to serialize a struct, I get the error LastElementNameNotAvailable Looking at the xml-rs code, that error is emitted after it fails to pop a name off of the stack.

https://github.com/netvl/xml-rs/blob/master/src/writer/emitter.rs#L351

So I'm guessing that it tried to call end_tag too many times?

I have these types (defined by the boto AWS s3 spec)


#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
#[derive(fake::Dummy)]
pub struct DeleteObjectsRequest {
    #[serde(skip)]
    pub bucket: BucketName,
    #[serde(skip)]
    pub bypass_governance_retention: Option<BypassGovernanceRetention>,
    #[serde(skip)]
    pub checksum_algorithm: Option<ChecksumAlgorithm>,
    pub delete: Delete,
    #[serde(skip)]
    pub expected_bucket_owner: Option<AccountId>,
    #[serde(skip)]
    pub mfa: Option<MFA>,
    #[serde(skip)]
    pub request_payer: Option<RequestPayer>,
}

// the relevant type is `Delete`  which is defined as 
#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
#[derive(fake::Dummy)]
pub struct Delete {
    pub objects: ObjectIdentifierList,
    pub quiet: Option<Quiet>,
}

#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
#[derive(fake::Dummy)]
pub struct ObjectIdentifier {
    pub key: ObjectKey,
    pub version_id: Option<ObjectVersionId>,
}
pub type ObjectIdentifierList = Vec<ObjectIdentifier>;
rrichardson commented 1 year ago

Here is the debug output:

2022-09-29T18:27:21.520Z DEBUG [serde_xml_rs::ser] Struct DeleteObjectsRequest
2022-09-29T18:27:21.520Z DEBUG [serde_xml_rs::ser::map] field delete
2022-09-29T18:27:21.520Z DEBUG [serde_xml_rs::ser] Struct Delete
2022-09-29T18:27:21.520Z DEBUG [serde_xml_rs::ser::map] field objects
2022-09-29T18:27:21.520Z DEBUG [serde_xml_rs::ser] Sequence
2022-09-29T18:27:21.520Z DEBUG [serde_xml_rs::ser] Struct ObjectIdentifier
2022-09-29T18:27:21.520Z DEBUG [serde_xml_rs::ser::map] field key
2022-09-29T18:27:21.520Z DEBUG [serde_xml_rs::ser::map] end field
2022-09-29T18:27:21.520Z DEBUG [serde_xml_rs::ser::map] field version_id
2022-09-29T18:27:21.520Z DEBUG [serde_xml_rs::ser] Some
2022-09-29T18:27:21.520Z DEBUG [serde_xml_rs::ser::map] end field
2022-09-29T18:27:21.520Z DEBUG [serde_xml_rs::ser] Struct ObjectIdentifier
2022-09-29T18:27:21.520Z DEBUG [serde_xml_rs::ser::map] field key
2022-09-29T18:27:21.520Z DEBUG [serde_xml_rs::ser::map] end field
2022-09-29T18:27:21.520Z DEBUG [serde_xml_rs::ser::map] field version_id
2022-09-29T18:27:21.520Z DEBUG [serde_xml_rs::ser] None
2022-09-29T18:27:21.520Z DEBUG [serde_xml_rs::ser::map] end field
2022-09-29T18:27:21.520Z DEBUG [serde_xml_rs::ser] Struct ObjectIdentifier
2022-09-29T18:27:21.520Z DEBUG [serde_xml_rs::ser::map] field key
2022-09-29T18:27:21.520Z DEBUG [serde_xml_rs::ser::map] end field
2022-09-29T18:27:21.520Z DEBUG [serde_xml_rs::ser::map] field version_id
2022-09-29T18:27:21.520Z DEBUG [serde_xml_rs::ser] Some
2022-09-29T18:27:21.520Z DEBUG [serde_xml_rs::ser::map] end field
burleight commented 1 year ago

+1

There is a bug when serializing Vec's of struct or enum. I'm working on a fix.

duckfromdiscord commented 1 year ago

I am having this issue now too, deserializing straight into a struct and converting it straight back gives this error. i do not get it when using serde_json::to_string, so it must be on serde-xml's end.

gustavowd commented 1 year ago

I am having tha same issue in this code:

use serde::{Deserialize, Serialize}; use serde_xml_rs::{from_str, to_string};

[derive(Debug, Default, Deserialize, Serialize)]

struct Video { id: u32, title: String, description: String, removed: bool, }

[derive(Debug, Default, Deserialize, Serialize)]

struct Videos {

[serde(rename = "Video")]

videos: Vec<Video>,

}

fn main() { //let file = File::open("videos.xml").expect("Unable to open file"); //let reader = BufReader::new(file); //let videos: Videos = from_reader(reader).expect("Unable to parse XML");

//println!("Videos: {:?}", videos);

let xml_string = r#"
    <Videos>
        <Video>
            <id>1</id>
            <title>Video 1</title>
            <description>This is the first video.</description>
            <removed>false</removed>
        </Video>
        <Video>
            <id>2</id>
            <title>Video 2</title>
            <description>This is the second video.</description>
            <removed>true</removed>
        </Video>
    </Videos>
"#;

let videos: Videos = from_str(xml_string).unwrap();
println!("{:#?}", videos);

let xml_str_out = to_string(&videos).unwrap();
println!("{}", xml_str_out);

}

That's the error: thread 'main' panicked at 'called Result::unwrap() on an Err value: Writer { source: LastElementNameNotAvailable }', src/main.rs:45:42

Any solution?

mlappo commented 1 year ago

I have exactly the same problem... Is there any workaround? In general vector serializing works, but if the struct has rename-serialize then it's broken...

#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename(serialize = "some-parameter"))] /// !!! This is a problem, commenting this line makes it work, but produces wrong XML
struct SomeParameter {
    key: String,
    value: String,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename(serialize = "some-session"))]
struct SomeSession {
    #[serde(rename = "$value")]
    some_parameters: Vec<SomeParameter>,
}
julienr commented 1 year ago

I managed to reduce it to this test case which fails for me on master:

#[test]
fn serialize_nested_collection() {
    #[derive(Debug, Serialize, PartialEq)]
    struct OuterCollection {
        a: Vec<A>,
    }

    #[derive(Debug, Serialize, PartialEq)]
    struct A {
        name: String,
    }

    let coll = OuterCollection {
        a: vec![A {
            name: "42".to_owned(),
        }],
    };

    let str = to_string(&coll).unwrap();
    println!("str={:?}", str);
}
running 1 test
thread 'serialize_nested_collection' panicked at 'called `Result::unwrap()` on an `Err` value: Writer { source: LastElementNameNotAvailable }', tests/test.rs:400:32
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
test serialize_nested_collection ... FAILED
oneslash commented 1 year ago

Oookay, I used this use quick_xml::se::to_string; instead of current crate and works like a charm

conqp commented 1 year ago

Thanks. I stumbled over this just now. It appears, that serde-xml-rs is dead.

han1548772930 commented 5 months ago

I also have the same error

gustavowd commented 5 months ago

@han1548772930, use the quick_xml library. Works like a charm. Example: Cargo.toml [dependencies] serde = { version = "1.0", features = ["derive"] } quick-xml = {version = "0.31.0", features = ["serialize"]}

Code: use serde::{Deserialize, Serialize}; use quick_xml::de::from_str as from_str; use quick_xml::se::to_string as to_string;

[derive(Debug, Default, Deserialize, Serialize)]

struct Video { id: u32,

[serde(rename = "Title")]

title: String,
description: String,
removed: bool,

}

[derive(Debug, Default, Deserialize, Serialize)]

struct Videos {

[serde(rename = "Video")]

`videos: Vec<Video>,`

}

fn main() { let xml_string = r#"`

`"#;

let videos: Videos = from_str(xml_string).unwrap();
println!("{:?}", videos);

let xml_str_out = to_string(&videos).unwrap();
println!("{}", xml_str_out);
han1548772930 commented 5 months ago

@han1548772930, use the quick_xml library. Works like a charm. Example: Cargo.toml [dependencies] serde = { version = "1.0", features = ["derive"] } quick-xml = {version = "0.31.0", features = ["serialize"]}

Code: use serde::{Deserialize, Serialize}; use quick_xml::de::from_str as from_str; use quick_xml::se::to_string as to_string;

[derive(Debug, Default, Deserialize, Serialize)] struct Video { id: u32, #[serde(rename = "Title")] title: String, description: String, removed: bool, }

[derive(Debug, Default, Deserialize, Serialize)] struct Videos { #[serde(rename = "Video")] videos: Vec<Video>, }

fn main() { let xml_string = r#"<Videos> <Video> <id>1</id> <Title>Video 1</Title> <description>This is the first video.</description> <removed>false</removed> </Video> <Video> <id>2</id> <Title>Video 2</Title> <description>This is the second video.</description> <removed>true</removed> </Video> </Videos>"#;

let videos: Videos = from_str(xml_string).unwrap();
println!("{:?}", videos);

let xml_str_out = to_string(&videos).unwrap();
println!("{}", xml_str_out);

yes I have switched to quick_xml

David-OConnor commented 1 month ago

Thanks for the advice. I'm also hitting this; switching to quick-xml

duckfromdiscord commented 1 month ago

I needed serde-xml-rs, though, because the XML I was working with from another program required order to be maintained