Deserialize complex YAML file in Rust

Rust

We already saw how to read and deserialize a simple YAML file in Rust and we saw a number of other aricles about YAML in Rust. This time we are going to see a rather complex YAML file. It is copied from the Kantoniko project which is a Ladino dictionary.

This file represents the word kaza with its tanslations to a number of languages.

examples/deserialize-yaml/kaza.yaml

grammar: NA
orijen: Jeneral

versions:
  - ladino: kaza
    rashi: קאזה

    gender: feminine
    number: singular

    translations:
        inglez:
          - house
          - home
        fransez: maison
        ebreo: בית
        portugez: casa
        kasteyano: casa
        turko: ev

  - ladino: kazas

    gender: feminine
    number: plural

    translations:
        inglez:
          - houses
          - homes
        fransez: ''
        ebreo: בתים
        portugez: casas
        kasteyano: casas
        turko: evler



Dependencies in Cargo.toml

examples/deserialize-yaml/Cargo.toml

[package]
name = "deserialize-yaml"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

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


examples/deserialize-yaml/src/main.rs

use serde::Deserialize;
use std::fs;


#[derive(Debug, Deserialize)]
struct Version {
    ladino: String,
    rashi: Option<String>,
}

#[derive(Debug, Deserialize)]
struct Word {
    grammar: String, // TODO fixed list 
    orijen: String, // TODO
    versions: Vec<Version>,
}

fn main() {
    let filename = get_filename();
    let text = fs::read_to_string(&filename).unwrap();

    let word: Word = serde_yaml::from_str(&text).unwrap_or_else(|err| {
        eprintln!("Could not parse YAML file: {err}");
        std::process::exit(1);
    });

    println!("grammar: {}", word.grammar);
    println!("orijen: {}", word.orijen);
    for version in &word.versions {
        println!("---");
        println!("ladino: {}", version.ladino);
        println!("rashi: {}", version.rashi);
    }


    if filename == "kaza.yaml" {
        assert_eq!(word.grammar, "NA");
        assert_eq!(word.orijen, "Jeneral");
        assert_eq!(word.versions[0].ladino, "kaza");
        assert_eq!(word.versions[1].ladino, "kazas");
    }
}

fn get_filename() -> String {
    let args: Vec<String> = std::env::args().collect();
    if args.len() != 2 {
        eprintln!("Usage: {} FILENAME", args[0]);
        std::process::exit(1);
    }
    args[1].to_string()
}

Author

Gabor Szabo (szabgab)

Gabor Szabo, the author of the Rust Maven web site maintains several Open source projects in Rust and while he still feels he has tons of new things to learn about Rust he already offers training courses in Rust and still teaches Python, Perl, git, GitHub, GitLab, CI, and testing.

Gabor Szabo