YAML is a human-readable data serialization format commonly used for configuration files and data exchange. This article demonstrates how to parse YAML content in Rust using serde.

Rust's serde provides functionality to serialize data structures into YAML format and deserialize YAML into Rust data structures.

Adding Dependencies

To use the serde library for parsing YAML text, you need to add serde and serde_yaml dependencies to your project.

Edit the Cargo.toml file and add the following:

[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.9"

Deserializing YAML into Structs

serde_yaml provides a serde_yaml::from_str function to parse YAML strings and automatically map them to Rust data structures.

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct Config {
    ip: String,
    port: u16, 
}

fn main() {

    let yaml = "
        ip: 127.0.0.1
        port: 34567
    ";

    let config:Config = serde_yaml::from_str(&yaml).unwrap();

    println!("{}:{}",config.ip,config.port);

}

Program Output

127.0.0.1:34567

Serializing Structs to YAML Strings

serde_yaml provides a serde_yaml::to_string function to convert Rust structs into YAML strings.

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct Config {
    ip: String,
    port: u16, 
}

fn main() {

    let config = Config{
        ip: "127.0.0.1".to_string(),
        port: 80
    };

    let yaml = serde_yaml::to_string(&config).unwrap();

    println!("{}",yaml);

}

Program Output

ip: 127.0.0.1
port: 80

Using YAML's !tag Syntax

Enums can use !tag syntax for serialization to identify variant names.

use serde::{Serialize, Deserialize};

#[derive(Debug, Serialize, Deserialize)]
enum Config {
    Name(String),
    Point{x:f64, y:f64},
    Elements(usize, usize, usize),
}

fn main() {

    let yaml1 = "
        - !Name perfcode.com
        - !Point {x: 1.0, y: 2.0}
        - !Elements [1, 2, 3]
    ";

    let v1: Vec<Config> = serde_yaml::from_str(yaml1).unwrap();

    println!("{:?}\n{:?}\n{:?}",v1[0],v1[1],v1[2]);

    let yaml2 = "
        - !Name perfcode.com
        - !Point
          x: 1.0
          y: 2.0
        - !Elements
          - 1
          - 2
          - 3
    ";

    let v2: Vec<Config> = serde_yaml::from_str(yaml2).unwrap();

    println!("{:?}\n{:?}\n{:?}",v2[0],v2[1],v2[2]);
}

Program Output

Name("perfcode.com")
Point { x: 1.0, y: 2.0 }
Elements(1, 2, 3)
Name("perfcode.com")
Point { x: 1.0, y: 2.0 }
Elements(1, 2, 3)