1个不稳定版本
0.6.0 | 2024年1月24日 |
---|
#1195 in 编码
66每月下载量
在2个crate中使用(通过bnr-xfs)
66KB
1.5K SLoC
serde-xml-rs
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