Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Impossible to deserialize a serialized object #653

Closed
igiona opened this issue Sep 18, 2023 · 2 comments
Closed

Impossible to deserialize a serialized object #653

igiona opened this issue Sep 18, 2023 · 2 comments
Labels
question serde Issues related to mapping from Rust types to XML

Comments

@igiona
Copy link

igiona commented Sep 18, 2023

I have a relatively simple XML to serialize and deserialize (a subset of https://en.wikipedia.org/wiki/XML-RPC):
The following code does properly serialize an Object into XML, but the deserialization of the serialized object itself doesn't work.
I'm using:

[[package]]
name = "quick-xml"
version = "0.30.0"

Any hint?

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
pub struct MethodResponse {
    pub params: Params,
}

#[derive(Serialize, Deserialize)]
pub struct Params {
    pub param: Vec<Param>,
}

#[derive(Serialize, Deserialize, Clone)]
pub struct Param {
    pub value: ValueElement,
}

#[derive(Serialize, Deserialize, Clone)]
pub struct ValueElement {
    pub v: Value,
}

#[derive(Serialize, Deserialize, Clone)]
pub enum Value {
    #[serde(rename = "int")]
    Int(i32),
    #[serde(rename = "double")]
    Double(f64),
    #[serde(rename = "bool")]
    Boolean(bool),
    #[serde(rename = "string")]
    String(String)
}
let obj = MethodResponse 
{ 
    params : Params {
                param : {
                    vec![
                        Param { value: ValueElement { v: Value::String("MyStringValue".to_string()) } },
                        Param { value: ValueElement { v: Value::Boolean(true) } },
                        Param { value: ValueElement { v: Value::Int(66) } },
                        Param { value: ValueElement { v: Value::Double(1.2) } },
                    ]
                }
            }
};

let xml = quick_xml::se::to_string(&obj).unwrap();
println!("{}", xml);
let object: MethodResponse = quick_xml::de::from_str(&xml).unwrap();

The serialized XML looks ok to me, and it's correctly printed:

<MethodResponse><params><param><value><string>Lol</string></value></param><param><value><bool>true</bool></value></param><param><value><int>66</int></value></param><param><value><double>1.2</double></value></param></params></MethodResponse>

But the deserialization on the other hand doesn't work and the program panics:

thread 'xmlrpc::response::tests::deserialize_should_succeed' panicked at 'called `Result::unwrap()` on an `Err` value: Custom("missing field `v`")', src\xmlrpc\response.rs:35:68
stack backtrace:
@Mingun
Copy link
Collaborator

Mingun commented Sep 19, 2023

You should add #[serde(rename = "$value")] to pub v: Value, because deserializer should known to which field it should redirect different tags (<string>, <bool>, etc.) and that field is a $value field. I think, we can emphasise that in the documentation something here.

Also, you should add #[serde(default)] to pub param: Vec<Param>, otherwise you'll get an error in attempt to deserialize a response with no parameters.

Also, note, that examples in https://docs.rs/quick-xml/latest/quick_xml/de/index.html#value are not correct. They are not tested and I've found that while working on fix for #630. Currently serialization without renames didn't produce <field/>, but actual enum variant tags, but deserialization didn't work.

@Mingun Mingun added question serde Issues related to mapping from Rust types to XML labels Sep 19, 2023
@igiona
Copy link
Author

igiona commented Sep 19, 2023

You should add #[serde(rename = "$value")] to pub v: Value, because deserializer should known to which field it should redirect different tags (<string>, <bool>, etc.) and that field is a $value field. I think, we can emphasise that in the documentation something here.

Also, you should add #[serde(default)] to pub param: Vec<Param>, otherwise you'll get an error in attempt to deserialize a response with no parameters.

Also, note, that examples in https://docs.rs/quick-xml/latest/quick_xml/de/index.html#value are not correct. They are not tested and I've found that while working on fix for #630. Currently serialization without renames didn't produce <field/>, but actual enum variant tags, but deserialization didn't work.

Hey @Mingun, many thanks for the fast response! Indeed your suggestions helped 🙏
Indeed the $value feature is not very simple to understand from the documentation, on the other hand probably you kind of assume some "serde" knowledge, which unfortunately I don't yet(?) have.

Again, many thanks for your support!

@igiona igiona closed this as completed Sep 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question serde Issues related to mapping from Rust types to XML
Projects
None yet
Development

No branches or pull requests

2 participants