#serialization #derive-debug #deserializer #fork #maintained #partial-eq #debugging

serde-xml-rust

基于xml-rs的Serde反序列化器(与0.9+兼容)的维护分支

1个不稳定版本

0.6.0 2024年1月24日

#1195 in 编码

Download history 25/week @ 2024-05-10 80/week @ 2024-05-17 90/week @ 2024-05-24 52/week @ 2024-05-31 31/week @ 2024-06-07 13/week @ 2024-06-14 5/week @ 2024-06-21 36/week @ 2024-07-05 13/week @ 2024-07-12 16/week @ 2024-07-19 1/week @ 2024-07-26

66每月下载量
2个crate中使用(通过bnr-xfs

MIT许可证

66KB
1.5K SLoC

serde-xml-rs

Build Status

xml-rs基于的Serde反序列化器(与1.0兼容)

示例用法

use serde::{Deserialize, Serialize};
use serde_xml_rs::{from_str, to_string};

#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Item {
    name: String,
    source: String,
}

fn main() {
    let src = r#"<Item><name>Banana</name><source>Store</source></Item>"#;
    let should_be = Item {
        name: "Banana".to_string(),
        source: "Store".to_string(),
    };

    let item: Item = from_str(src).unwrap();
    assert_eq!(item, should_be);

    let reserialized_item = to_string(&item).unwrap();
    assert_eq!(src, reserialized_item);
}

lib.rs:

Serde XML

XML是一种灵活的标记语言,仍然用于在应用程序之间共享数据或编写配置文件。

Serde XML提供了一种将文本和强类型Rust数据结构之间进行转换的方法。

注意事项

Serde框架主要是为了考虑像JSON或YAML这样的格式而设计的。与XML相比,这些格式具有更严格的语法优势,这使得可以在不依赖于伴随的架构的情况下知道字段的类型,并且不允许在同一对象中重复相同的标签。

例如,以下文档的YAML编码并不简单。

<document>
  <header>A header</header>
  <section>First section</section>
  <section>Second section</section>
  <sidenote>A sidenote</sidenote>
  <section>Third section</section>
  <sidenote>Another sidenote</sidenote>
  <section>Fourth section</section>
  <footer>The footer</footer>
</document>

一种可能性是以下YAML文档。

- header: A header
- section: First section
- section: Second section
- sidenote: A sidenote
- section: Third section
- sidenote: Another sidenote
- section: Fourth section
- footer: The footer

其他显著差异

  • XML需要一个有名称的根节点。
  • XML有一个命名空间系统。
  • XML区分属性、子标签和内容。
  • 在XML中,节点的顺序有时很重要。

基本示例

use serde::{Deserialize, Serialize};
use serde_xml_rs::{from_str, to_string};

#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Item {
    name: String,
    source: String,
}

fn main() {
    let src = r#"<?xml version="1.0" encoding="UTF-8"?><Item><name>Banana</name><source>Store</source></Item>"#;
    let should_be = Item {
        name: "Banana".to_string(),
        source: "Store".to_string(),
    };

    let item: Item = from_str(src).unwrap();
    assert_eq!(item, should_be);

    let reserialized_item = to_string(&item).unwrap();
    assert_eq!(src, reserialized_item);
}

标签内容


#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Document {
    content: Content
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Content {
    #[serde(rename = "$value")]
    value: String
}

fn main() {
    let src = r#"<document><content>Lorem ipsum</content></document>"#;
    let document: Document = from_str(src).unwrap();
    assert_eq!(document.content.value, "Lorem ipsum");
}

重复的标签


#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct PlateAppearance {
    #[serde(rename = "$value")]
    events: Vec<Event>
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "kebab-case")]
enum Event {
    Pitch(Pitch),
    Runner(Runner),
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Pitch {
    speed: u32,
    r#type: PitchType,
    outcome: PitchOutcome,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
enum PitchType { FourSeam, TwoSeam, Changeup, Cutter, Curve, Slider, Knuckle, Pitchout }

#[derive(Debug, Serialize, Deserialize, PartialEq)]
enum PitchOutcome { Ball, Strike, Hit }

#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Runner {
    from: Base, to: Option<Base>, outcome: RunnerOutcome,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
enum Base { First, Second, Third, Home }
#[derive(Debug, Serialize, Deserialize, PartialEq)]
enum RunnerOutcome { Steal, Caught, PickOff }

fn main() {
    let document = r#"
        <plate-appearance>
          <pitch speed="95" type="FourSeam" outcome="Ball" />
          <pitch speed="91" type="FourSeam" outcome="Strike" />
          <pitch speed="85" type="Changeup" outcome="Ball" />
          <runner from="First" to="Second" outcome="Steal" />
          <pitch speed="89" type="Slider" outcome="Strike" />
          <pitch speed="88" type="Curve" outcome="Hit" />
        </plate-appearance>"#;
    let plate_appearance: PlateAppearance = from_str(document).unwrap();
    assert_eq!(plate_appearance.events[0], Event::Pitch(Pitch { speed: 95, r#type: PitchType::FourSeam, outcome: PitchOutcome::Ball }));
}

自定义EventReader

use serde::{Deserialize, Serialize};
use serde_xml_rs::{from_str, to_string, de::Deserializer};
use xml::reader::{EventReader, ParserConfig};

#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Item {
    name: String,
    source: String,
}

fn main() {
    let src = r#"<Item><name>  Banana  </name><source>Store</source></Item>"#;
    let should_be = Item {
        name: "  Banana  ".to_string(),
        source: "Store".to_string(),
    };

    let config = ParserConfig::new()
        .trim_whitespace(false)
        .whitespace_to_characters(true);
    let event_reader = EventReader::new_with_config(src.as_bytes(), config);
    let item = Item::deserialize(&mut Deserializer::new(event_reader)).unwrap();
    assert_eq!(item, should_be);
}

依赖项

~0.7–1.3MB
~28K SLoC