media-io / yaserde

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

Unable to serialize a struct that deserialization works for #162

Closed tatupesonen closed 10 months ago

tatupesonen commented 10 months ago

I'm trying to serialize/deserialize some data that an API responds with. This is what the XML from the API looks like:

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soapenv:Body>
        <LoginResponse xmlns="urn:vim25">
             <returnval>
                <userName>username_here</userName>
                <loggedInAt>datetime_here</loggedInAt>
            </returnval>
        </LoginResponse>
    </soapenv:Body>
</soapenv:Envelope>

And this is my code:

#[derive(Deserialize, Debug, Serialize)]
#[serde(rename = "soapenv:Envelope")]
pub struct SoapResponse {
    #[serde(rename = "@xmlns:soapenc")]
    soapenc: Option<String>,
    #[serde(rename = "@xmlns:soapenv")]
    soapenv: Option<String>,
    #[serde(rename = "@xmlns:xsd")]
    xsd: Option<String>,
    #[serde(rename = "@xmlns:xsi")]
    xsi: Option<String>,
    #[serde(rename = "$value")]
    pub body: SoapBody,
}

#[derive(Deserialize, Debug, Serialize)]
pub struct SoapBody {
    #[serde(rename = "$value")]
    pub response_type: Response,
}

#[derive(Deserialize, Debug, Serialize)]
pub enum Response {
    #[serde(rename = "LoginResponse")]
    LoginResponse {
        #[serde(rename = "@xmlns")]
        xmlns: String,
        #[serde(rename = "$value")]
        returnval: LoginResponse,
    },
    #[serde(rename = "Other")]
    SomeOther {},
}

#[derive(Deserialize, Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct LoginResponse {
    logged_in_at: String,
    user_name: String,
}

Deserialization works fine. However, when I try to serialize a structure like this:

use quick_xml::se::to_string;

let thing = SoapResponse {
    soapenc: None,
    soapenv: None,
    xsd: None,
    xsi: None,
    body: {
        SoapBody {
            response_type: Response::LoginResponse {
                xmlns: "urn:vim25".into(),
                returnval: LoginResponse {
                    logged_in_at: "example".into(),
                    user_name: "example".into(),
                },
            },
        }
    },
};
let thing = to_string(&thing);
dbg!(&thing);

I get

 Err(
    Unsupported(
        "serialization of struct `SoapBody` is not supported in `$value` field",
    ),
)

What could be the reason that causes this?

Versions:

quick-xml 0.30.0 with features = ["serde", "serialize", "arbitrary", "serde-types", "overlapped-lists", "document-features", "encoding", "encoding_rs"]
Rust 1.72