Merge pull request #46 from DmitrySamoylov/fix-nested-namespaces

Fix (de)serialization for elements with nested namespaces
This commit is contained in:
Marc-Antoine ARNAUD 2020-02-18 10:47:36 +01:00 committed by GitHub
commit 389077e17c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 96 additions and 21 deletions

View File

@ -98,6 +98,10 @@ impl<'de, R: Read> Deserializer<R> {
Ok(()) Ok(())
} }
pub fn depth(&self) -> usize {
self.depth
}
pub fn set_map_value(&mut self) { pub fn set_map_value(&mut self) {
self.is_map_value = true; self.is_map_value = true;
} }

View File

@ -89,6 +89,41 @@ fn de_struct_namespace() {
); );
} }
#[test]
fn de_struct_namespace_nested() {
#[derive(YaDeserialize, Default, PartialEq, Debug)]
#[yaserde(prefix = "nsa", namespace = "nsa: http://www.sample.com/ns/a")]
struct A {
#[yaserde(prefix = "nsa")]
alpha: i32,
}
#[derive(YaDeserialize, Default, PartialEq, Debug)]
#[yaserde(prefix = "nsb", namespace = "nsb: http://www.sample.com/ns/b")]
struct B {
// Note that name `nested` resides in `nsb` though it has a type from `nsa`
#[yaserde(prefix = "nsb")]
nested: A,
}
convert_and_validate!(
r#"
<?xml version="1.0" encoding="utf-8"?>
<nsb:B
xmlns:nsa="http://www.sample.com/ns/a"
xmlns:nsb="http://www.sample.com/ns/b">
<nsb:nested>
<nsa:alpha>32</nsa:alpha>
</nsb:nested>
</nsb:B>
"#,
B,
B {
nested: A { alpha: 32 }
}
);
}
#[test] #[test]
fn de_enum_namespace() { fn de_enum_namespace() {
#[derive(YaDeserialize, PartialEq, Debug)] #[derive(YaDeserialize, PartialEq, Debug)]

View File

@ -9,9 +9,17 @@ use yaserde::ser::to_string;
use yaserde::YaSerialize; use yaserde::YaSerialize;
macro_rules! convert_and_validate { macro_rules! convert_and_validate {
($model:expr, $content:expr) => { ($model: expr, $content: expr) => {
let data: Result<String, String> = to_string(&$model); let data: Result<String, String> = to_string(&$model);
assert_eq!(data, Ok(String::from($content))); assert_eq!(
data,
Ok(
String::from($content)
.split("\n")
.map(|s| s.trim())
.collect::<String>()
)
);
}; };
} }
@ -152,3 +160,35 @@ fn ser_struct_default_namespace() {
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><tt xmlns=\"http://www.w3.org/ns/ttml\" xmlns:ttm=\"http://www.w3.org/ns/ttml#metadata\"><item>something</item></tt>"; let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><tt xmlns=\"http://www.w3.org/ns/ttml\" xmlns:ttm=\"http://www.w3.org/ns/ttml#metadata\"><item>something</item></tt>";
convert_and_validate!(model, content); convert_and_validate!(model, content);
} }
#[test]
fn de_struct_namespace_nested() {
#[derive(YaSerialize, Default, PartialEq, Debug)]
#[yaserde(prefix = "nsa", namespace = "nsa: http://www.sample.com/ns/a")]
struct A {
#[yaserde(prefix = "nsa")]
alpha: i32,
}
#[derive(YaSerialize, Default, PartialEq, Debug)]
#[yaserde(prefix = "nsb", namespace = "nsb: http://www.sample.com/ns/b")]
struct B {
// Note that name `nested` resides in `nsb` though it has a type from `nsa`
#[yaserde(prefix = "nsb")]
nested: A,
}
convert_and_validate!(
B {
nested: A { alpha: 32 }
},
r#"
<?xml version="1.0" encoding="utf-8"?>
<nsb:B xmlns:nsb="http://www.sample.com/ns/b">
<nsb:nested xmlns:nsa="http://www.sample.com/ns/a">
<nsa:alpha>32</nsa:alpha>
</nsb:nested>
</nsb:B>
"#
);
}

View File

@ -17,9 +17,8 @@ pub fn parse(
let namespaces_matches: TokenStream = namespaces let namespaces_matches: TokenStream = namespaces
.iter() .iter()
.map(|(p, ns)| { .map(|(p, ns)| {
let str_ns = ns.as_str(); if prefix.as_ref() == Some(p) {
if *prefix == Some(p.to_string()) { Some(quote!(#ns => {}))
Some(quote!(#str_ns => {}))
} else { } else {
None None
} }
@ -382,15 +381,17 @@ pub fn parse(
}; };
debug!("Struct: start to parse {:?}", named_element); debug!("Struct: start to parse {:?}", named_element);
if let Some(ref namespace) = struct_namespace { if reader.depth() == 0 {
match namespace.as_str() { if let Some(ref namespace) = struct_namespace {
#namespaces_matches match namespace.as_str() {
bad_ns => { #namespaces_matches
let msg = format!("bad namespace for {}, found {}", named_element, bad_ns); bad_ns => {
return Err(msg); let msg = format!("bad namespace for {}, found {}", named_element, bad_ns);
return Err(msg);
}
} }
} }
}; }
#variables #variables
#field_visitors #field_visitors

View File

@ -405,15 +405,10 @@ pub fn serialize(
let skip = writer.skip_start_end(); let skip = writer.skip_start_end();
if !skip { if !skip {
if let Some(label) = writer.get_start_event_name() { let label = writer.get_start_event_name().unwrap_or_else(|| #root.to_string());
let struct_start_event = XmlEvent::start_element(label.as_ref()); let struct_start_event = XmlEvent::start_element(label.as_ref())#add_namespaces;
#build_attributes #build_attributes
let _ret = writer.write(struct_start_event); let _ret = writer.write(struct_start_event);
} else {
let struct_start_event = XmlEvent::start_element(#root)#add_namespaces;
#build_attributes
let _ret = writer.write(struct_start_event);
}
} }
#struct_inspector #struct_inspector