简体   繁体   English

Rust serde 如何反序列化 xml “奇怪”列表?

[英]Rust serde How deserialize xml “weird” lists?

Im trying to deserialize this style of xml list that are not technically a list but behaves like one:我试图反序列化这种风格的 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>

The number of items on the "list" is variable and will only increment the number(x) on the id-0000x . “列表”上的项目数是可变的,只会增加id-0000x上的数字(x)。

The issue is that i cant think how to map this to a Rust struct using serde.问题是我想不出如何使用 serde 将 map 转换为 Rust 结构。

Im trying to do something like this:我试图做这样的事情:


#[derive(Debug, Default, Deserialize)]
#[serde(rename = "list")]
struct List {
    people: Vec<Person>
}

#[derive(Debug, Default, Deserialize)]
struct Person {
    name: String,
    age: u8
}

but I don't know how to deal with the id-0000x tags.但我不知道如何处理id-0000x标签。

Edit: this are the dependencies that im using:编辑:这是我使用的依赖项:

[dependencies]
serde = { version = "1.0.117", features = ["derive"] }
serde-xml-rs = "0.4.0"

Thanks for the help in advance.我在这里先向您的帮助表示感谢。 Regards问候

Probably easiest just to deserialize the tags:反序列化标签可能最简单:

struct List(BTreeMap<String, Person>);

This will get you an ordered collection of "id-bla" => Person pairs.这将为您提供有序的“id-bla”=> Person 对集合。

Thanks to the Tomas Hurst suggestion if solve the issues using something like this:感谢 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(())
}

output: output:

List { list: [Person { name: "Pedro", age: 37 }, Person { name: "Alex", age: 30 }] }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM