serde能否反序列化格式为扁平键值对的XML数据?
解决方案
你遇到的这种<key>和值节点交替排列的扁平XML结构,serde-xml-rs没有内置的serde属性可以直接一步映射到你定义的Data结构体,可通过以下两种方式实现需求:
方案一:中间层转换(实现成本最低,推荐)
先解析为你目前已经实现的元组Vec中间结构,再手动映射为目标结构体:#[derive(Deserialize)] enum Node { #[serde(rename = "int")] Int(u32), #[serde(rename = "string")] String(String), } #[derive(Deserialize)] struct DataTemp { #[serde(rename = "$value")] entries: Vec<(String, Node)>, } struct Data { version: Node, name: Node, } // 解析转换逻辑 let xml_str = r#" <data> <key>version</key> <int>4</int> <key>name</key> <string>John</string> </data> "#; let temp: DataTemp = serde_xml_rs::from_str(xml_str)?; let mut entries_iter = temp.entries.into_iter(); let data = Data { version: entries_iter.find(|(k, _)| k == "version").unwrap().1, name: entries_iter.find(|(k, _)| k == "name").unwrap().1, };方案二:自定义
Data的反序列化逻辑(可直接一步解析)
为Data手动实现Deserializetrait,主动处理交替的key-value结构:use serde::de::{Deserialize, Deserializer, MapAccess, Visitor}; use std::fmt; impl<'de> Deserialize<'de> for Data { fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>, { struct DataVisitor; impl<'de> Visitor<'de> for DataVisitor { type Value = Data; fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("alternating key and value nodes") } fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error> where A: MapAccess<'de>, { let mut version = None; let mut name = None; while let Some(key) = map.next_key::<String>()? { match key.as_str() { "version" => version = Some(map.next_value()?), "name" => name = Some(map.next_value()?), _ => { let _: Node = map.next_value()?; } } } Ok(Data { version: version.ok_or_else(|| serde::de::Error::missing_field("version"))?, name: name.ok_or_else(|| serde::de::Error::missing_field("name"))?, }) } } deserializer.deserialize_map(DataVisitor) } } // 直接解析即可得到Data实例 let data: Data = serde_xml_rs::from_str(xml_str)?;
内容的提问来源于stack exchange,提问作者Vigdail
相关产品推荐
相关产品推荐

