Rust XML序列化与反序列化库yaserde_derive的使用,高效实现Rust结构体与XML格式互转
Rust XML序列化与反序列化库yaserde_derive的使用,高效实现Rust结构体与XML格式互转
目标
该库支持XML的序列化和反序列化,并提供所有特定功能。
支持的类型
- 结构体(Struct)
- 向量(Vec)
- 枚举(Enum)
- 包含复杂类型的枚举(Enum with complex types)
- 可选类型(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_derive进行XML序列化和反序列化:
use yaserde_derive::{YaDeserialize, YaSerialize};
// 定义可序列化/反序列化的结构体
#[derive(Debug, YaSerialize, YaDeserialize)]
#[yaserde(
root = "book",
namespace = "ns: http://example.com"
)]
pub struct Book {
#[yaserde(attribute)]
id: String,
#[yaserde(rename = "title")]
name: String,
#[yaserde(skip_serializing_if = "Option::is_none")]
author: Option<String>,
#[yaserde(rename = "price")]
cost: f64,
#[yaserde(text)]
description: String,
}
fn main() {
// 创建Book实例
let book = Book {
id: "123".to_string(),
name: "Rust Programming".to_string(),
author: Some("John Doe".to_string()),
cost: 29.99,
description: "A book about Rust programming".to_string(),
};
// 序列化为XML
let xml = yaserde::ser::to_string(&book).unwrap();
println!("Serialized XML:\n{}", xml);
// 反序列化回结构体
let deserialized_book: Book = yaserde::de::from_str(&xml).unwrap();
println!("Deserialized struct:\n{:?}", deserialized_book);
}
这个示例展示了:
- 定义了一个带有各种yaserde属性的Book结构体
- 创建了一个Book实例
- 将其序列化为XML字符串
- 从XML字符串反序列化回Book结构体
输出结果将显示序列化后的XML和反序列化后的结构体内容。
完整示例代码
// 引入必要的库
use yaserde_derive::{YaDeserialize, YaSerialize};
// 定义一个表示用户的结构体
#[derive(Debug, PartialEq, YaSerialize, YaDeserialize)]
#[yaserde(
root = "user",
namespace = "example: http://example.org"
)]
struct User {
#[yaserde(attribute, rename = "user_id")]
id: u32,
#[yaserde(rename = "full_name")]
name: String,
#[yaserde(skip_serializing_if = "Option::is_none")]
email: Option<String>,
#[yaserde(flatten)]
address: Address,
#[yaserde(rename = "active")]
is_active: bool,
#[yaserde(text)]
bio: String,
}
// 定义地址结构体
#[derive(Debug, PartialEq, YaSerialize, YaDeserialize)]
struct Address {
street: String,
city: String,
zip_code: String,
}
fn main() {
// 创建User实例
let user = User {
id: 42,
name: "Alice Smith".to_string(),
email: Some("alice@example.com".to_string()),
address: Address {
street: "123 Main St".to_string(),
city: "New York".to_string(),
zip_code: "10001".to_string(),
},
is_active: true,
bio: "Software developer with Rust experience".to_string(),
};
// 序列化为XML
let xml_data = yaserde::ser::to_string(&user).unwrap();
println!("序列化后的XML:\n{}", xml_data);
// 反序列化回User结构体
let deserialized_user: User = yaserde::de::from_str(&xml_data).unwrap();
println!("\n反序列化后的结构体:\n{:#?}", deserialized_user);
// 验证序列化和反序列化是否一致
assert_eq!(user, deserialized_user);
println!("\n验证通过:序列化和反序列化结果一致");
}
这个示例展示了:
- 定义了一个更复杂的User结构体,包含嵌套结构体Address
- 使用了多种yaserde属性(attribute, rename, skip_serializing_if, flatten, text等)
- 实现了完整的序列化和反序列化流程
- 包含了验证步骤确保数据一致性
输出结果将显示序列化后的XML格式和反序列化后的User结构体内容。
1 回复
Rust XML序列化与反序列化库yaserde_derive的使用
简介
yaserde_derive是一个Rust库,用于实现结构体与XML格式之间的序列化和反序列化。它通过过程宏提供了一种简单的方式来标注Rust结构体,使其能够与XML相互转换。
主要特性
- 支持结构体与XML的相互转换
- 提供自定义标签名、命名空间等配置选项
- 支持属性序列化
- 类型安全的数据转换
使用方法
1. 添加依赖
首先在Cargo.toml中添加依赖:
[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,
title: String,
author: String,
#[yaserde(rename = "pub_date")]
publication_date: String,
}
fn main() {
let book = Book {
id: "1".to_string(),
title: "Rust Programming".to_string(),
author: "John Doe".to_string(),
publication_date: "2023-01-01".to_string(),
};
// 序列化为XML
let xml = yaserde::ser::to_string(&book).unwrap();
println!("Serialized XML:\n{}", xml);
// 反序列化回结构体
let deserialized: Book = yaserde::de::from_str(&xml).unwrap();
println!("Deserialized: {:?}", deserialized);
}
3. 输出示例
序列化后的XML可能如下:
<?xml version="1.0" encoding="utf-8"?>
<book id="1">
<title>Rust Programming</title>
<author>John Doe</author>
<pub_date>2023-01-01</pub_date>
</book>
4. 高级配置选项
命名空间支持
#[derive(YaSerialize, YaDeserialize, PartialEq, Debug)]
#[yaserde(
rename = "book",
namespace = "ns: http://example.com/namespace"
)]
pub struct Book {
#[yaserde(attribute, prefix = "ns")]
id: String,
// ...
}
嵌套结构
#[derive(YaSerialize, YaDeserialize, PartialEq, Debug)]
pub struct Library {
#[yaserde(rename = "book")]
books: Vec<Book>,
}
枚举支持
#[derive(YaSerialize, YaDeserialize, PartialEq, Debug)]
pub enum BookType {
#[yaserde(rename = "paperback")]
Paperback,
#[yaserde(rename = "hardcover")]
Hardcover,
#[yaserde(rename = "ebook")]
EBook,
}
完整示例demo
下面是一个结合了上述所有特性的完整示例:
use yaserde_derive::{YaDeserialize, YaSerialize};
// 定义书籍类型枚举
#[derive(YaSerialize, YaDeserialize, PartialEq, Debug)]
pub enum BookType {
#[yaserde(rename = "paperback")]
Paperback,
#[yaserde(rename = "hardcover")]
Hardcover,
#[yaserde(rename = "ebook")]
EBook,
}
// 定义书籍结构体,包含命名空间和属性
#[derive(YaSerialize, YaDeserialize, PartialEq, Debug)]
#[yaserde(
rename = "book",
namespace = "ns: http://example.com/namespace"
)]
pub struct Book {
#[yaserde(attribute, prefix = "ns")]
id: String,
title: String,
author: String,
#[yaserde(rename = "pub_date")]
publication_date: String,
#[yaserde(rename = "type")]
book_type: BookType,
}
// 定义图书馆结构体,包含嵌套的书籍集合
#[derive(YaSerialize, YaDeserialize, PartialEq, Debug)]
pub struct Library {
#[yaserde(rename = "book")]
books: Vec<Book>,
}
fn main() {
// 创建图书馆数据
let library = Library {
books: vec![
Book {
id: "1".to_string(),
title: "Rust Programming".to_string(),
author: "John Doe".to_string(),
publication_date: "2023-01-01".to_string(),
book_type: BookType::Paperback,
},
Book {
id: "2".to_string(),
title: "Advanced Rust".to_string(),
author: "Jane Smith".to_string(),
publication_date: "2023-02-15".to_string(),
book_type: BookType::Hardcover,
},
],
};
// 序列化为XML
let xml = yaserde::ser::to_string(&library).unwrap();
println!("Serialized XML:\n{}", xml);
// 反序列化回结构体
let deserialized: Library = yaserde::de::from_str(&xml).unwrap();
println!("Deserialized: {:?}", deserialized);
}
注意事项
- 默认情况下,字段名会转换为小写作为XML标签名
- 可以使用
#[yaserde(rename = "...")]
自定义标签名 - 使用
#[yaserde(attribute)]
将字段序列化为XML属性而非子元素 - 对于Option类型,值为None时默认不会序列化
yaserde_derive提供了一种高效且类型安全的方式来处理Rust结构体与XML之间的转换,特别适合需要与XML接口交互的应用场景。