Rust XML序列化与反序列化库yaserde的使用,yaserde提供高效安全的XML数据转换框架
Rust XML序列化与反序列化库yaserde的使用,yaserde提供高效安全的XML数据转换框架
目标
该库支持XML的序列化和反序列化,并提供所有特定功能。
支持的类型
- 结构体(Struct)
- 向量(Vec)
- 枚举(Enum)
- 带有复杂类型的枚举
- 可选类型(Option)
- 字符串(String)
- 布尔值(bool)
- 数字(u8, i8, u32, i32, f32, f64)
属性
- attribute: 将字段定义为属性
- default: 定义初始化字段的默认函数
- flatten: 展平字段内容
- namespace: 定义字段的命名空间
- rename: 重命名字段
- root: 重命名基础元素。仅用于XML根元素。
- skip_serializing: 从序列化输出中排除此字段
- skip_serializing_if: 如果条件为真,则跳过此字段的序列化
- text: 此字段匹配文本内容
自定义序列化/反序列化
任何类型都可以定义自定义的序列化器和/或反序列化器。要实现它,需要定义YaDeserialize/YaSerialize的实现:
impl YaDeserialize for MyType {
fn deserialize<R: Read>(reader: &mut yaserde::de::Deserializer<R>) -> Result<Self, String> {
// 反序列化代码
}
}
impl YaSerialize for MyType {
fn serialize<W: Write>(&self, writer: &mut yaserde::ser::Serializer<W>) -> Result<(), String> {
// 序列化代码
}
}
完整示例
下面是一个完整的示例,展示如何使用yaserde进行XML的序列化和反序列化:
use yaserde_derive::{YaSerialize, YaDeserialize};
use std::fs::File;
use std::io::Read;
// 定义一个结构体并实现序列化和反序列化
#[derive(YaSerialize, YaDeserialize, PartialEq, Debug)]
#[yaserde(root = "book")]
pub struct Book {
#[yaserde(attribute)]
id: String,
title: String,
author: String,
#[yaserde(rename = "publish_date")]
date: String,
#[yaserde(skip_serializing_if = "Vec::is_empty")]
categories: Vec<String>,
}
fn main() {
// 创建一个Book实例
let book = Book {
id: "123".to_string(),
title: "Rust Programming".to_string(),
author: "John Doe".to_string(),
date: "2023-01-01".to_string(),
categories: vec!["Programming".to_string(), "Rust".to_string()],
};
// 序列化为XML
let xml_data = yaserde::ser::to_string(&book).unwrap();
println!("Serialized XML:\n{}", xml_data);
// 从XML反序列化
let mut file = File::open("book.xml").unwrap();
let mut xml_string = String::new();
file.read_to_string(&mut xml_string).unwrap();
let deserialized_book: Book = yaserde::de::from_str(&xml_string).unwrap();
println!("Deserialized book: {:?}", deserialized_book);
}
这个示例展示了:
- 定义一个带有各种属性的结构体
- 使用yaserde进行序列化为XML字符串
- 从XML文件反序列化为Rust结构体
要运行这个示例,需要在Cargo.toml中添加以下依赖:
[dependencies]
yaserde = "0.12.0"
yaserde_derive = "0.12.0"
另一个完整示例
下面是一个更复杂的示例,展示嵌套结构体和枚举的使用:
use yaserde_derive::{YaSerialize, YaDeserialize};
use std::io::Write;
// 定义一个枚举类型
#[derive(YaSerialize, YaDeserialize, PartialEq, Debug)]
pub enum BookType {
#[yaserde(rename = "technical")]
Technical,
#[yaserde(rename = "fiction")]
Fiction,
#[yaserde(rename = "biography")]
Biography,
}
// 定义一个嵌套结构体
#[derive(YaSerialize, YaDeserialize, PartialEq, Debug)]
pub struct Publisher {
name: String,
#[yaserde(attribute)]
country: String,
}
// 主结构体
#[derive(YaSerialize, YaDeserialize, PartialEq, Debug)]
#[yaserde(root = "library")]
pub struct Library {
#[yaserde(rename = "book")]
books: Vec<Book>,
publisher: Publisher,
#[yaserde(attribute)]
version: String,
}
fn main() {
// 创建Library实例
let library = Library {
version: "1.0".to_string(),
books: vec![
Book {
id: "001".to_string(),
title: "Rust in Action".to_string(),
author: "Tim McNamara".to_string(),
date: "2021-08-01".to_string(),
categories: vec!["Programming".to_string(), "Rust".to_string()],
book_type: BookType::Technical,
},
Book {
id: "002".to_string(),
title: "The Martian".to_string(),
author: "Andy Weir".to_string(),
date: "2014-02-11".to_string(),
categories: vec!["Science Fiction".to_string()],
book_type: BookType::Fiction,
},
],
publisher: Publisher {
name: "Manning Publications".to_string(),
country: "US".to_string(),
},
};
// 序列化为XML
let xml_data = yaserde::ser::to_string(&library).unwrap();
println!("Serialized XML:\n{}", xml_data);
// 写入文件
let mut file = File::create("library.xml").unwrap();
file.write_all(xml_data.as_bytes()).unwrap();
// 从文件反序列化
let mut file = File::open("library.xml").unwrap();
let mut xml_string = String::new();
file.read_to_string(&mut xml_string).unwrap();
let deserialized_lib: Library = yaserde::de::from_str(&xml_string).unwrap();
println!("Deserialized library: {:?}", deserialized_lib);
}
这个示例展示了:
- 枚举类型的序列化和反序列化
- 嵌套结构体的处理
- 更复杂的XML结构
- 将XML写入文件和从文件读取
1 回复
Rust XML序列化与反序列化库yaserde使用指南
yaserde是一个Rust语言的XML序列化与反序列化库,提供了高效安全的XML数据转换框架。它类似于serde但专门针对XML格式,支持将Rust数据结构与XML文档相互转换。
主要特性
- 支持序列化(Serialize)和反序列化(Deserialize)
- 基于属性(attribute)的配置方式
- 支持命名空间(namespace)
- 类型安全的XML处理
- 高性能的XML解析与生成
使用方法
1. 添加依赖
首先在Cargo.toml中添加yaserde依赖:
[dependencies]
yaserde = "0.8"
yaserde_derive = "0.8"
2. 基本示例
use yaserde_derive::{YaDeserialize, YaSerialize};
#[derive(YaSerialize, YaDeserialize, PartialEq, Debug)]
#[yaserde(rename = "book")]
pub struct Book {
#[yaserde(attribute)]
id: String,
#[yaserde(rename = "title")]
name: String,
author: String,
#[yaserde(rename = "pub_date")]
date: String,
#[yaserde(skip)]
secret: String,
}
fn main() {
let book = Book {
id: "123".to_string(),
name: "Rust编程".to_string(),
author: "张三".to_string(),
date: "2023-01-01".to_string(),
secret: "不序列化的字段".to_string(),
};
// 序列化为XML
let xml_data = yaserde::ser::to_string(&book).unwrap();
println!("序列化结果:\n{}", xml_data);
// 反序列化回对象
let book2: Book = yaserde::de::from_str(&xml_data).unwrap();
println!("反序列化结果:\n{:?}", book2);
}
3. 输出结果
序列化输出:
<?xml version="1.0" encoding="utf-8"?>
<book id="123">
<title>Rust编程</title>
<author>张三</author>
<pub_date>2023-01-01</pub_date>
</book>
反序列化输出:
Book {
id: "123",
name: "Rust编程",
author: "张三",
date: "2023-01-01",
secret: ""
}
高级用法
1. 命名空间支持
#[derive(YaSerialize, YaDeserialize, PartialEq, Debug)]
#[yaserde(
rename = "book",
namespace = "ns: http://example.com/namespace"
)]
pub struct Book {
#[yaserde(attribute, namespace = "ns")]
id: String,
#[yaserde(rename = "title", namespace = "ns")]
name: String,
}
2. 枚举支持
#[derive(YaSerialize, YaDeserialize, PartialEq, Debug)]
#[yaserde(rename = "status")]
pub enum Status {
#[yaserde(rename = "available")]
Available,
#[yaserde(rename = "sold")]
Sold,
#[yaserde(rename = "reserved")]
Reserved,
}
3. 自定义格式化
#[derive(YaSerialize, YaDeserialize, PartialEq, Debug)]
#[yaserde(rename = "person")]
pub struct Person {
#[yaserde(attribute)]
id: u32,
#[yaserde(rename = "full_name")]
name: String,
#[yaserde(
rename = "birth_date",
format = "YYYY-MM-DD",
default = "1900-01-01"
)]
birth: String,
}
配置选项
yaserde提供了多种配置属性:
rename
: 重命名元素或属性attribute
: 标记为XML属性而非元素skip
: 跳过序列化/反序列化default
: 指定默认值namespace
: 定义命名空间prefix
: 命名空间前缀format
: 自定义格式化
性能建议
- 对于大型XML文件,考虑使用流式处理
- 尽可能重用已分配的缓冲区
- 避免不必要的字符串转换
- 使用
#[yaserde(skip)]
跳过不需要的字段
错误处理
yaserde提供了详细的错误信息,建议使用?
操作符或map_err
处理可能的错误:
let book: Book = yaserde::de::from_str(xml_str)
.map_err(|e| {
eprintln!("XML解析错误: {}", e);
e
})?;
yaserde是Rust生态中处理XML的优秀选择,特别适合需要类型安全和高性能的XML处理场景。
完整示例代码
// 引入必要的derive宏
use yaserde_derive::{YaDeserialize, YaSerialize};
// 定义一个带命名空间的Book结构体
#[derive(YaSerialize, YaDeserialize, PartialEq, Debug)]
#[yaserde(
rename = "book",
namespace = "ns: http://example.com/namespace"
)]
pub struct Book {
#[yaserde(attribute, namespace = "ns")]
id: String,
#[yaserde(rename = "title", namespace = "ns")]
name: String,
#[yaserde(namespace = "ns")]
author: String,
#[yaserde(rename = "pub_date", namespace = "ns")]
date: String,
#[yaserde(skip)]
secret: String,
}
// 定义一个状态枚举
#[derive(YaSerialize, YaDeserialize, PartialEq, Debug)]
#[yaserde(rename = "status")]
pub enum Status {
#[yaserde(rename = "available")]
Available,
#[yaserde(rename = "sold")]
Sold,
#[yaserde(rename = "reserved")]
Reserved,
}
fn main() {
// 创建Book实例
let book = Book {
id: "123".to_string(),
name: "Rust编程".to_string(),
author: "张三".to_string(),
date: "2023-01-01".to_string(),
secret: "不序列化的字段".to_string(),
};
// 序列化为XML
let xml_data = yaserde::ser::to_string(&book).unwrap();
println!("序列化结果:\n{}", xml_data);
// 反序列化回对象
let book2: Book = yaserde::de::from_str(&xml_data).unwrap();
println!("反序列化结果:\n{:?}", book2);
// 枚举序列化示例
let status = Status::Available;
let status_xml = yaserde::ser::to_string(&status).unwrap();
println!("状态序列化结果:\n{}", status_xml);
// 枚举反序列化示例
let status2: Status = yaserde::de::from_str("<status>available</status>").unwrap();
println!("状态反序列化结果:\n{:?}", status2);
}