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);
}

这个示例展示了:

  1. 定义一个带有各种属性的结构体
  2. 使用yaserde进行序列化为XML字符串
  3. 从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);
}

这个示例展示了:

  1. 枚举类型的序列化和反序列化
  2. 嵌套结构体的处理
  3. 更复杂的XML结构
  4. 将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: 自定义格式化

性能建议

  1. 对于大型XML文件,考虑使用流式处理
  2. 尽可能重用已分配的缓冲区
  3. 避免不必要的字符串转换
  4. 使用#[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);
}
回到顶部