如何用serde-xml-rs反序列化带任意属性的_flow-tags_标签?
完全可以用serde-xml实现需求,大部分场景下无需自定义反序列化/序列化器,通过serde的内置属性配置就能把<flow-tags>的属性提取为映射或列表。
1. 提取为映射(HashMap)
serde-xml支持用#[serde(flatten)]属性将未知属性直接序列化为HashMap,只需在对应结构体字段上标记该属性即可。
示例结构体定义:
use serde::Deserialize; use std::collections::HashMap; #[derive(Debug, Deserialize)] struct Event { #[serde(rename = "detail")] detail: Detail, } #[derive(Debug, Deserialize)] struct Detail { #[serde(rename = "_flow-tags_")] flow_tags: FlowTags, } #[derive(Debug, Deserialize)] struct FlowTags { #[serde(flatten)] attributes: HashMap<String, String>, }
反序列化后,flow_tags.attributes就是包含ASV_h91: "2024-04-19T00:36:52Z"的HashMap。
2. 提取为列表(Vec<(String, String)>)
如果需要将属性键值对转为列表,同样借助#[serde(flatten)],将字段类型设为Vec<(String, String)>,serde会自动把所有属性转换为键值对列表。
修改FlowTags结构体:
#[derive(Debug, Deserialize)] struct FlowTags { #[serde(flatten)] attributes: Vec<(String, String)>, }
反序列化后,flow_tags.attributes就是包含("ASV_h91", "2024-04-19T00:36:52Z")的Vec。
3. 完整示例代码
use serde::Deserialize; use std::collections::HashMap; use serde_xml_rs::from_str; #[derive(Debug, Deserialize)] struct Event { #[serde(rename = "detail")] detail: Detail, } #[derive(Debug, Deserialize)] struct Detail { #[serde(rename = "_flow-tags_")] flow_tags: FlowTags, } // 用HashMap的版本 #[derive(Debug, Deserialize)] struct FlowTags { #[serde(flatten)] attributes: HashMap<String, String>, } // // 用Vec的版本,取消注释即可替换 // #[derive(Debug, Deserialize)] // struct FlowTags { // #[serde(flatten)] // attributes: Vec<(String, String)>, // } fn main() { let xml = r#"<?xml version="1.0" standalone="yes"?> <event time="2024-04-19T00:36:52Z"> <detail> <_flow-tags_ ASV_h91="2024-04-19T00:36:52Z" /> </detail> </event>"#; let event: Event = from_str(xml).unwrap(); println!("{:#?}", event); }
运行代码后,就能看到<flow-tags>的属性被成功提取为对应的HashMap或Vec。
关于自定义反序列化器
只有当你需要对属性值做特殊类型转换(比如把时间字符串转为DateTime类型),或者有其他定制化逻辑时,才需要编写自定义反序列化器。普通的键值对提取用上述方法完全足够。
内容的提问来源于stack exchange,提问作者Kit Plummer
相关产品推荐
相关产品推荐

