macro_rules! impl_deserialize_for_internally_tagged_enum {
    (
        $enum:ty,
        $tag:literal,
        $(
            ($variant_tag:literal => $($variant:tt)+ )
        ),* $(,)?
    ) => { ... };
}
Available on crate feature serde-types only.
Expand description

A helper to implement Deserialize for internally tagged enums which does not use Deserializer::deserialize_any that produces wrong results with XML because of serde#1183.

In contrast to deriving Deserialize this macro assumes that a tag will be the first element or attribute in the XML.

Example

use quick_xml::de::from_str;
use quick_xml::impl_deserialize_for_internally_tagged_enum;
use serde::Deserialize;

#[derive(Deserialize, Debug, PartialEq)]
struct Root {
    one: InternallyTaggedEnum,
    two: InternallyTaggedEnum,
    three: InternallyTaggedEnum,
}

#[derive(Debug, PartialEq)]
// #[serde(tag = "@tag")]
enum InternallyTaggedEnum {
    Unit,
    Newtype(Newtype),
    Struct {
        // #[serde(rename = "@attribute")]
        attribute: u32,
        element: f32,
    },
}

#[derive(Deserialize, Debug, PartialEq)]
struct Newtype {
    #[serde(rename = "@attribute")]
    attribute: u64,
}

// The macro needs the type of the enum, the tag name,
// and information about all the variants
impl_deserialize_for_internally_tagged_enum!{
    InternallyTaggedEnum, "@tag",
    ("Unit"    => Unit),
    ("Newtype" => Newtype(Newtype)),
    ("Struct"  => Struct {
        #[serde(rename = "@attribute")]
        attribute: u32,
        element: f32,
    }),
}

assert_eq!(
    from_str::<Root>(r#"
        <root>
            <one tag="Unit" />
            <two tag="Newtype" attribute="42" />
            <three tag="Struct" attribute="42">
                <element>4.2</element>
            </three>
        </root>
    "#).unwrap(),
    Root {
        one: InternallyTaggedEnum::Unit,
        two: InternallyTaggedEnum::Newtype(Newtype { attribute: 42 }),
        three: InternallyTaggedEnum::Struct {
            attribute: 42,
            element: 4.2,
        },
    },
);