Unable to serialize a struct that deserialization works for

Open
#654 4 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
48/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Stale
Tech stack
rust
Domain
backend

Research direction

Start by reading the Serde serialization handling for $value fields and the tests covering nested structs in that position; the payload does not name specific files. Reproduce the reported error with quick-xml 0.30.0 and the SoapResponse example. Done means serialization succeeds for this structure, with a regression test covering the case.

Written by the indexing model from the issue text.

Description

bug serde

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
Dominant language
Rust
Stars
1.6k
Forks
299
Avg merge
2d 4h
Merged PRs (30d)
9

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from tafia/quick-xml

All issues in tafia/quick-xml

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.