Rust serde 如何反序列化 xml "weird" 列表?
Rust serde How deserialize xml "weird" lists?
我正在尝试反序列化这种类型的 xml 列表,它在技术上不是列表,但表现得像一个列表:
<list>
<id-00001>
<name type="string">Pedro</name>
<age type="number">37</age>
</id-00001>
<id-00002>
<name type="string">Alex</name>
<age type="number">30</age>
</id-00002>
<list>
“列表”上的项目数量是可变的,只会增加 id-0000x
上的数字 (x)。
问题是我想不出如何使用 serde 将其映射到 Rust 结构。
我正在尝试做这样的事情:
#[derive(Debug, Default, Deserialize)]
#[serde(rename = "list")]
struct List {
people: Vec<Person>
}
#[derive(Debug, Default, Deserialize)]
struct Person {
name: String,
age: u8
}
但我不知道如何处理 id-0000x
标签。
编辑:
这是我使用的依赖项:
[dependencies]
serde = { version = "1.0.117", features = ["derive"] }
serde-xml-rs = "0.4.0"
提前感谢您的帮助。
此致
反序列化标签可能最简单:
struct List(BTreeMap<String, Person>);
这将为您提供有序的“id-bla”集合 => 人物对。
感谢 Tomas Hurst 的建议,如果使用这样的方法解决问题:
use serde::{Deserialize, Deserializer}; // 1.0.94
use serde_xml_rs;
use std::collections::HashMap;
const XML: &str = r#"
<?xml version="1.0" encoding="utf-8"?>
<root version="1">
<list>
<id-00001>
<name type="string">Pedro</name>
<age type="number">37</age>
</id-00001>
<id-00002>
<name type="string">Alex</name>
<age type="number">30</age>
</id-00002>
</list>
</root>
"#;
#[derive(Debug, Default, Deserialize)]
struct List {
#[serde(deserialize_with = "deserialize_list")]
list: Vec<Person>,
}
#[derive(Debug, Default, Deserialize, Clone)]
struct Person {
name: String,
age: u8,
}
fn deserialize_list<'de, D>(d: D) -> Result<Vec<Person>, D::Error>
where
D: Deserializer<'de>,
{
let people_raw: HashMap<String, Person> = Deserialize::deserialize(d)?;
let people: Vec<Person> = people_raw.values().map(|person| person.clone()).collect();
Ok(people)
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let data: List = serde_xml_rs::from_str(XML)?;
println!("{:?}", data);
Ok(())
}
输出:
List { list: [Person { name: "Pedro", age: 37 }, Person { name: "Alex", age: 30 }] }
我正在尝试反序列化这种类型的 xml 列表,它在技术上不是列表,但表现得像一个列表:
<list>
<id-00001>
<name type="string">Pedro</name>
<age type="number">37</age>
</id-00001>
<id-00002>
<name type="string">Alex</name>
<age type="number">30</age>
</id-00002>
<list>
“列表”上的项目数量是可变的,只会增加 id-0000x
上的数字 (x)。
问题是我想不出如何使用 serde 将其映射到 Rust 结构。
我正在尝试做这样的事情:
#[derive(Debug, Default, Deserialize)]
#[serde(rename = "list")]
struct List {
people: Vec<Person>
}
#[derive(Debug, Default, Deserialize)]
struct Person {
name: String,
age: u8
}
但我不知道如何处理 id-0000x
标签。
编辑: 这是我使用的依赖项:
[dependencies]
serde = { version = "1.0.117", features = ["derive"] }
serde-xml-rs = "0.4.0"
提前感谢您的帮助。 此致
反序列化标签可能最简单:
struct List(BTreeMap<String, Person>);
这将为您提供有序的“id-bla”集合 => 人物对。
感谢 Tomas Hurst 的建议,如果使用这样的方法解决问题:
use serde::{Deserialize, Deserializer}; // 1.0.94
use serde_xml_rs;
use std::collections::HashMap;
const XML: &str = r#"
<?xml version="1.0" encoding="utf-8"?>
<root version="1">
<list>
<id-00001>
<name type="string">Pedro</name>
<age type="number">37</age>
</id-00001>
<id-00002>
<name type="string">Alex</name>
<age type="number">30</age>
</id-00002>
</list>
</root>
"#;
#[derive(Debug, Default, Deserialize)]
struct List {
#[serde(deserialize_with = "deserialize_list")]
list: Vec<Person>,
}
#[derive(Debug, Default, Deserialize, Clone)]
struct Person {
name: String,
age: u8,
}
fn deserialize_list<'de, D>(d: D) -> Result<Vec<Person>, D::Error>
where
D: Deserializer<'de>,
{
let people_raw: HashMap<String, Person> = Deserialize::deserialize(d)?;
let people: Vec<Person> = people_raw.values().map(|person| person.clone()).collect();
Ok(people)
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let data: List = serde_xml_rs::from_str(XML)?;
println!("{:?}", data);
Ok(())
}
输出:
List { list: [Person { name: "Pedro", age: 37 }, Person { name: "Alex", age: 30 }] }