serde_yaml 库:在 Rust 中使用 YAML
YAML(YAML Ain't Markup Language)是最流行的数据序列化格式之一,广泛用于配置文件、数据结构描述以及服务间的信息交换。在 Rust 生态系统中,有一个成熟且高性能的库 serde_yaml,它基于强大的序列化框架 serde 构建。在本文中,我们将详细讲解如何在 Rust 中解析、创建和处理 YAML 文档。
安装与引入
首先,将以下依赖项添加到您的 Cargo.toml 中:
[dependencies]serde = { version = "1.0", features = ["derive"] }serde_yaml = "0.9"serde_yaml 库会自动引入解析和生成 YAML 所需的所有组件。
基本反序列化(YAML → Rust 结构体)
最常见的场景是读取配置文件。定义一个与 YAML 文档对应的结构体:
use serde::Deserialize;
#[derive(Debug, Deserialize)]struct Config { server: ServerConfig, database: DatabaseConfig,}
#[derive(Debug, Deserialize)]struct ServerConfig { host: String, port: u16, workers: Option<u32>,}
#[derive(Debug, Deserialize)]struct DatabaseConfig { url: String, pool_size: u32,}现在读取 YAML 文件并将其转换为结构体:
use std::fs;
fn main() -> Result<(), Box<dyn std::error::Error>> { let yaml_content = fs::read_to_string("config.yaml")?; let config: Config = serde_yaml::from_str(&yaml_content)?; println!("服务器: {}:{}", config.server.host, config.server.port); println!("数据库: {}", config.database.url); Ok(())}config.yaml 文件示例:
server: host: "127.0.0.1" port: 8080 workers: 4database: url: "postgres://user:pass@localhost/db" pool_size: 10序列化(Rust 结构体 → YAML)
反向过程——从内存中的数据创建 YAML 文档:
use serde::Serialize;
#[derive(Debug, Serialize)]struct Project { name: String, version: String, dependencies: Vec<Dependency>,}
#[derive(Debug, Serialize)]struct Dependency { name: String, version: String, optional: bool,}
fn main() -> Result<(), Box<dyn std::error::Error>> { let project = Project { name: "my-app".to_string(), version: "0.1.0".to_string(), dependencies: vec![ Dependency { name: "serde".to_string(), version: "1.0".to_string(), optional: false, }, Dependency { name: "tokio".to_string(), version: "1.35".to_string(), optional: true, }, ], };
let yaml_string = serde_yaml::to_string(&project)?; println!("{}", yaml_string); // 保存到文件 std::fs::write("project.yaml", &yaml_string)?; Ok(())}处理任意 YAML 文档
有时 YAML 的结构是未知的。在这种情况下,使用 serde_yaml::Value:
use serde_yaml::Value;
fn main() -> Result<(), Box<dyn std::error::Error>> { let yaml_data = "apiVersion: v1kind: Servicemetadata: name: my-service labels: app: webspec: ports: - port: 80 targetPort: 8080 selector: app: web"; let value: Value = serde_yaml::from_str(yaml_data)?; // 访问嵌套数据 if let Some(ports) = value["spec"]["ports"].as_sequence() { for port in ports { if let Some(port_num