Biblioteca serde_yaml: trabajo con YAML en Rust
YAML (YAML Ain't Markup Language) es uno de los formatos de serialización de datos más populares, ampliamente utilizado para archivos de configuración, descripción de estructuras de datos e intercambio de información entre servicios. En el ecosistema de Rust, existe una biblioteca madura y eficiente llamada serde_yaml, construida sobre el potente framework de serialización serde. En este artículo, analizaremos en detalle cómo analizar, crear y procesar documentos YAML en Rust.
Instalación y configuración
Para comenzar, agregue las siguientes dependencias a su Cargo.toml:
[dependencies]serde = { version = "1.0", features = ["derive"] }serde_yaml = "0.9"La biblioteca serde_yaml incorporará automáticamente todos los componentes necesarios para el análisis y la generación de YAML.
Deserialización básica (YAML → estructura de Rust)
El escenario más común es la lectura de un archivo de configuración. Definamos una estructura que corresponda al documento 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,}Ahora leamos el archivo YAML y lo transformemos en una estructura:
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!("Servidor: {}:{}", config.server.host, config.server.port); println!("Base de datos: {}", config.database.url); Ok(())}Ejemplo del archivo config.yaml:
server: host: "127.0.0.1" port: 8080 workers: 4database: url: "postgres://user:pass@localhost/db" pool_size: 10Serialización (estructura de Rust → YAML)
El proceso inverso: crear un documento YAML a partir de datos en memoria:
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); // Guardamos en un archivo std::fs::write("project.yaml", &yaml_string)?; Ok(())}Trabajo con documentos YAML arbitrarios
A veces la estructura del YAML no se conoce de antemano. En esos casos, use 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)?; // Acceso a datos anidados if let Some(ports) = value["spec"]["ports"].as_sequence() { for port in ports { if let Some(port_num