serde-xml-rs
serde-xml-rs copied to clipboard
attributes serialization
How to serialise attributes on XML items ? I d'ont see anything for that. Any suggestion ?
Yea attributes are a weird thing. I'm not sure how to handle them. We could rename fields to something like %foo
, where the %
denotes that the field is meant to be an attribute. This would require one to annotate all attributes, but would work quite nicely I think and remove all confusion we have currently in the deserializer.
Yep I think like in every library who manage XML ... It's still the same problem of naming. But yep adding a prefix can made sense (which need to be a parameter) because with that we can generate reversible JSON.
This would require one to annotate all attributes, but would work quite nicely I think and remove all confusion we have currently in the deserializer.
I agree, also was thinking about this approach to ensure roundtrips. Could avoid most annotations by using something like attr_width
vs sub_item
by default, but maybe that will be even more verbose?
Could avoid most annotations by using something like attr_width vs sub_item by default, but maybe that will be even more verbose?
You mean to require adding %
for non-attributes?
@oli-obk I mean to avoid any annotations and instead use prefixes for struct fields (which is essentially the same, just perhaps more convenient).
hmm.. I don't like that, because it exposes xml stuff to users of the struct who don't even care about xml
Maybe... although author can still add annotations to rename it if it's a public structure / fields and not just for internal usage.
Probably you already know of it, but here there's a nice overview of some of the most common mapping conventions for attributes (and namespaces). The main problem is, there's all kind of conventions. Maybe a plugin system to allow choosing one's preferred method would be best?
I think an annotation would be a good choice. Maybe #[xml(attribute)]
.
I think an annotation would be a good choice. Maybe #[xml(attribute)].
Serde has no support for such features. serde-xml
is just a serde
format, we can't create features that serde
doesn't have and we can't parse extra attributes.
We'll also need to enforce that attribute-fields come before regular fields, because the serializer cannot look ahead. This is probably only doable with a runtime error though.
So, may be like $value, but more complex #[serde(rename = "$xml:attr:name")]
#[serde(rename = "$xml:value")]
@anton-dutov Wouldn't that also affect json serializaton because it's #[serde(rename)]
?
@Boscop Just for case where only xml (seri/deseri)lization used, on other cases modification of serde required
#[rename(field, target=json)]
#[rename(Field, target=xml)]
field: Type
it's interesting @anton-dutov, in this formulation #[serde(rename = "$xml:attr:name")]
we can also address the namespace like: #[serde(rename = "$xml:ns:name")]
(issue #50).
On my side it looks the most relevant solution.
@MarcAntoine-Arnaud, @Boscop
Continue discussion in #62
Hello guys, is this feature supported now?
For anyone here in the future, this is implemented at least I am on 0.6.0
#[derive(Serialize, Deserialize)]
pub struct Layout {
#[serde(rename = "control")]
pub control: Vec<Control>,
#[serde(rename = "@height")]
pub height: String,
#[serde(rename = "@width")]
pub width: String,
}
Anything renamed with the @ will map to an attribute, otherwise they will be treated as a child component.
Note that the @
is only for serialization. You should not use it for deserialization. Extending the example above:
use serde::{Deserialize, Serialize};
use serde_xml_rs::{from_str, to_string};
#[derive(Debug, Serialize, Deserialize)]
pub struct Control {
name: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Layout {
#[serde(rename(serialize = "@height"))]
pub height: String,
#[serde(rename(serialize = "@width"))]
pub width: String,
#[serde(rename = "control")]
pub control: Control,
}
fn main() {
let xml = r#"
<Layout height="3" width="5">
<control>
<name>Hello World!</name>
</control>
</Layout>
"#;
let layout: Layout = from_str(xml).unwrap();
println!("{layout:#?}");
println!("{}", to_string(&layout).unwrap());
}
will output:
Layout {
height: "3",
width: "5",
control: Control {
name: "Hello World!",
},
}
<?xml version="1.0" encoding="UTF-8"?><Layout height="3" width="5"><control><name>Hello World!</name></control></Layout>