Serde - trouble "flattening" enum variant

Hello,

i am trying to serialize enumeration with quick-xml crate like:

use serde::Serialize;

#[derive(Debug, Serialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum Datastore {
    Running,
    Candidate,
    Other(String),
}

#[derive(Debug, Serialize}
pub struct Root {
    target: Target
}

#[derive(Debug, Serialize}
pub struct Target {
    #[serde(rename = "$value")]
    datastore: Datastore
}

For plain enum variants, all is ok - e.g. Datastore::Running, the output is as needed:

<target><running/></target>

I have problems with "unpacking" the single tuple variant... E.g. for Datastore::Other("custom"), i need following:

<target><custom/></target>

but default derived serialization does:

<target><other><custom/></other></target>

I managed to "bypass" part of problem and remove "other" tags with custom serializer:

impl Serialize for Datastore {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let s = match self {
            Datastore::Other(s) => s.as_str(),
            Datastore::Running => "running",
            Datastore::Candidate => "candidate",
        };
        serializer.serialize_str(s)
    }
}

Which unfortunately de-tags all the enum variants, insterad of <running/> i get running, etc.
Serde examples or explanations are not that great in regard on what is all the magic with serializer methods or fn declaration, and how can one customize/change the type of the transformed element.

When i try to replace serialize_str() with other .serialize_...(), i get various compliation errors on lieftimes or different types (vs S:: which i have no understanding on what it refers to in my specific case).

What is the proper approach to achieve above serialization?

please note that manually wrapping s in < / /> seems not to work, as the output with above code is:

<target>&lt;custom/&gt;</target>

istead of expected:

<target><custom/></target>

(i know it's correctly corresponding html codes, but wouldn't expect it to be changed by 'itself"/serializer for my xml dump/output needed for TCP communication)

The derived implementation uses serialize_unit_variant instead of serialize_str. You can see what the derives expand to with "cargo expand", for example, on the playground. If you use the same function, you should see the same XML output. It requires you to have a &'static str. What you want might not be easily possible with serde.

Thank you for feedback & tips! :slight_smile:

I spent last few evenings browsing the XML ecosystem and trying to find usable crates.
Current state feels not that great, most of the crates seem to be stuck/abbandoned with pending PRs & no feedback to months old issues.
(Various problems that i have seem to have been opened by other people as well in the past for some crates with no feedback)

It looks like the most productive approach will be taking some low level xml readers/writers and do the tree build & (de)serialization for my RPCs explicitly/manually.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.