serde 可以使用平面键值对反序列化 XML 吗?
Can serde deserialize XML with flat key value pairs?
我正在使用 serde-xml-rs 箱子。我有 XML,格式如下:
<data>
<key>version</key>
<int>4</int>
<key>name</key>
<string>John</string>
</data>
是否可以将其解析为这样的结构?
enum Node {
#[serde(rename="int")]
Int(u32),
#[serde(rename="string")]
String(String),
}
struct Data {
// what serde attributes to use???
version: Node,
name: Node,
}
我只是设法将其解析为 Vec
个元组:
#[serde(rename = "$value")]
data: Vec<(String, Node)>,
据我所知,使用 Deserialize
derive 宏无法完成您想做的事情。但是,您仍然可以实现您的目标:Serde 允许您 manually implement Deserialize
在派生宏不够强大的情况下。
如果您的代码需要高性能,您可能希望完全手动实现 Deserialize
;否则,您也可以像上面那样先反序列化为元组,然后从中构建 Data
结构。这会更容易,因为您不需要直接与 Deserializer
交互,但由于中间数据表示,性能可能不如完全手动执行。
下面是一个利用中间元组表示的解决方案。
#[derive(serde::Deserialize, Debug)]
enum Node {
#[serde(rename="int")]
Int(u32),
#[serde(rename="string")]
String(String),
}
#[derive(Debug)]
struct Data {
version: Node,
name: Node,
}
impl<'de> serde::Deserialize<'de> for Data {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
use serde::de::Error;
#[derive(serde::Deserialize, Debug)]
struct IntermediateResult {
#[serde(rename = "$value")]
data: Vec<(String, Node)>,
}
// first, deserialize to the tuple via the macro generated Serialize implementation
let intermediate_result: IntermediateResult = IntermediateResult::deserialize(deserializer)?;
// find the keys we are looking for and save the values
let mut version: Option<Node> = None;
let mut name: Option<Node> = None;
for key_value_pair in intermediate_result.data {
let value_to_assign: &mut Option<Node> = match &*key_value_pair.0 {
"version" => &mut version,
"name" => &mut name,
_ => {
// handle unknown <key> – either ignore it or return an error; I am going to ignore it
continue;
}
};
*value_to_assign = Some(key_value_pair.1);
}
// if the required keys are missing, fail
if version.is_none() {
return Err(D::Error::custom("Did not find a <key> with content \"version\""));
}
if name.is_none() {
return Err(D::Error::custom("Did not find a <key> with content \"name\""));
}
// otherwise, build Data struct
Ok(Data {
version: version.unwrap(),
name: name.unwrap()
})
}
}
fn main() {
let xml = r###"
<data>
<key>version</key>
<int>4</int>
<key>name</key>
<string>John</string>
</data>
"###;
let data: Data = serde_xml_rs::from_str(xml).unwrap();
println!("{:?}", data);
}
我正在使用 serde-xml-rs 箱子。我有 XML,格式如下:
<data>
<key>version</key>
<int>4</int>
<key>name</key>
<string>John</string>
</data>
是否可以将其解析为这样的结构?
enum Node {
#[serde(rename="int")]
Int(u32),
#[serde(rename="string")]
String(String),
}
struct Data {
// what serde attributes to use???
version: Node,
name: Node,
}
我只是设法将其解析为 Vec
个元组:
#[serde(rename = "$value")]
data: Vec<(String, Node)>,
据我所知,使用 Deserialize
derive 宏无法完成您想做的事情。但是,您仍然可以实现您的目标:Serde 允许您 manually implement Deserialize
在派生宏不够强大的情况下。
如果您的代码需要高性能,您可能希望完全手动实现 Deserialize
;否则,您也可以像上面那样先反序列化为元组,然后从中构建 Data
结构。这会更容易,因为您不需要直接与 Deserializer
交互,但由于中间数据表示,性能可能不如完全手动执行。
下面是一个利用中间元组表示的解决方案。
#[derive(serde::Deserialize, Debug)]
enum Node {
#[serde(rename="int")]
Int(u32),
#[serde(rename="string")]
String(String),
}
#[derive(Debug)]
struct Data {
version: Node,
name: Node,
}
impl<'de> serde::Deserialize<'de> for Data {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
use serde::de::Error;
#[derive(serde::Deserialize, Debug)]
struct IntermediateResult {
#[serde(rename = "$value")]
data: Vec<(String, Node)>,
}
// first, deserialize to the tuple via the macro generated Serialize implementation
let intermediate_result: IntermediateResult = IntermediateResult::deserialize(deserializer)?;
// find the keys we are looking for and save the values
let mut version: Option<Node> = None;
let mut name: Option<Node> = None;
for key_value_pair in intermediate_result.data {
let value_to_assign: &mut Option<Node> = match &*key_value_pair.0 {
"version" => &mut version,
"name" => &mut name,
_ => {
// handle unknown <key> – either ignore it or return an error; I am going to ignore it
continue;
}
};
*value_to_assign = Some(key_value_pair.1);
}
// if the required keys are missing, fail
if version.is_none() {
return Err(D::Error::custom("Did not find a <key> with content \"version\""));
}
if name.is_none() {
return Err(D::Error::custom("Did not find a <key> with content \"name\""));
}
// otherwise, build Data struct
Ok(Data {
version: version.unwrap(),
name: name.unwrap()
})
}
}
fn main() {
let xml = r###"
<data>
<key>version</key>
<int>4</int>
<key>name</key>
<string>John</string>
</data>
"###;
let data: Data = serde_xml_rs::from_str(xml).unwrap();
println!("{:?}", data);
}