Add a derive attribute for deserialization of enum internally tagged via an attribute
This commit is contained in:
parent
f5cb114a71
commit
0b8a7968f1
@ -357,3 +357,39 @@ fn unnamed_enum() {
|
||||
serialize_and_validate!(model, content);
|
||||
deserialize_and_validate!(content, model, XmlStruct);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tagged_enum() {
|
||||
#[derive(Debug, PartialEq, YaSerialize, YaDeserialize, Default)]
|
||||
#[yaserde(tag = "type")]
|
||||
enum XmlEnum {
|
||||
#[default]
|
||||
#[yaserde(rename = "foo")]
|
||||
Foo,
|
||||
#[yaserde(rename = "bar")]
|
||||
Bar,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, YaSerialize, YaDeserialize, Default)]
|
||||
struct XmlStruct {
|
||||
#[yaserde(rename = "foobar")]
|
||||
foo_bar: XmlEnum,
|
||||
}
|
||||
|
||||
let model = XmlEnum::Foo;
|
||||
let content = "<base type=\"foo\"/>";
|
||||
// serialize_and_validate!(model, content);
|
||||
deserialize_and_validate!(content, model, XmlEnum);
|
||||
|
||||
let model = XmlEnum::Bar;
|
||||
let content = "<base type=\"bar\"/>";
|
||||
// serialize_and_validate!(model, content);
|
||||
deserialize_and_validate!(content, model, XmlEnum);
|
||||
|
||||
let model = XmlStruct {
|
||||
foo_bar: XmlEnum::Foo,
|
||||
};
|
||||
let content = "<base><foobar type=\"foo\"/></base>";
|
||||
// serialize_and_validate!(model, content);
|
||||
deserialize_and_validate!(content, model, XmlStruct);
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ pub struct YaSerdeAttribute {
|
||||
pub namespaces: BTreeMap<Option<String>, String>,
|
||||
pub prefix: Option<String>,
|
||||
pub rename: Option<String>,
|
||||
pub tag: Option<String>,
|
||||
pub skip_serializing: bool,
|
||||
pub skip_serializing_if: Option<String>,
|
||||
pub text: bool,
|
||||
@ -40,6 +41,7 @@ impl YaSerdeAttribute {
|
||||
let mut namespaces = BTreeMap::new();
|
||||
let mut prefix = None;
|
||||
let mut rename = None;
|
||||
let mut tag = None;
|
||||
let mut skip_serializing = false;
|
||||
let mut skip_serializing_if = None;
|
||||
let mut text = false;
|
||||
@ -82,6 +84,9 @@ impl YaSerdeAttribute {
|
||||
"rename" => {
|
||||
rename = get_value(&mut attr_iter);
|
||||
}
|
||||
"tag" => {
|
||||
tag = get_value(&mut attr_iter);
|
||||
}
|
||||
"skip_serializing" => {
|
||||
skip_serializing = true;
|
||||
}
|
||||
@ -107,6 +112,7 @@ impl YaSerdeAttribute {
|
||||
namespaces,
|
||||
prefix,
|
||||
rename,
|
||||
tag,
|
||||
skip_serializing,
|
||||
skip_serializing_if,
|
||||
text,
|
||||
@ -182,6 +188,7 @@ fn parse_empty_attributes() {
|
||||
namespaces: BTreeMap::new(),
|
||||
prefix: None,
|
||||
rename: None,
|
||||
tag: None,
|
||||
skip_serializing: false,
|
||||
skip_serializing_if: None,
|
||||
text: false,
|
||||
@ -232,6 +239,7 @@ fn parse_attributes() {
|
||||
namespaces: BTreeMap::new(),
|
||||
prefix: None,
|
||||
rename: None,
|
||||
tag: None,
|
||||
skip_serializing: false,
|
||||
skip_serializing_if: None,
|
||||
text: false,
|
||||
@ -282,6 +290,7 @@ fn only_parse_yaserde_attributes() {
|
||||
namespaces: BTreeMap::new(),
|
||||
prefix: None,
|
||||
rename: None,
|
||||
tag: None,
|
||||
skip_serializing: false,
|
||||
skip_serializing_if: None,
|
||||
text: false,
|
||||
@ -338,6 +347,7 @@ fn parse_attributes_with_values() {
|
||||
namespaces,
|
||||
prefix: None,
|
||||
rename: None,
|
||||
tag: None,
|
||||
skip_serializing: false,
|
||||
skip_serializing_if: None,
|
||||
text: false,
|
||||
|
||||
@ -24,6 +24,20 @@ pub fn parse(
|
||||
|
||||
let flatten = root_attributes.flatten;
|
||||
|
||||
let element_name = if let Some(tag) = &root_attributes.tag {
|
||||
quote! {
|
||||
attributes
|
||||
.iter()
|
||||
.find(|attr| attr.name.local_name.as_str() == #tag)
|
||||
.ok_or(format!("Expected enum tagged with {}, found {:?}", #tag, event))?
|
||||
.value.as_str()
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
name.local_name.as_str()
|
||||
}
|
||||
};
|
||||
|
||||
quote! {
|
||||
impl ::yaserde::YaDeserialize for #name {
|
||||
#[allow(unused_variables)]
|
||||
@ -50,7 +64,7 @@ pub fn parse(
|
||||
::yaserde::__derive_trace!("Enum {} @ {}: matching {:?}", stringify!(#name), start_depth, event);
|
||||
match event {
|
||||
::yaserde::__xml::reader::XmlEvent::StartElement { ref name, ref attributes, .. } => {
|
||||
match name.local_name.as_str() {
|
||||
match #element_name {
|
||||
#match_to_enum
|
||||
_named_element => {
|
||||
let _root = reader.next_event();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user