#serde-yaml #dbt #macro

macro dbt-yaml_derive

Derive macros for dbt-yaml

5 releases

Uses new Rust 2024

new 0.9.4 Apr 11, 2026
0.9.3 Apr 3, 2026
0.9.2 Mar 9, 2026
0.9.1 Feb 11, 2026
0.9.0 Feb 8, 2026

#13 in #dbt

Download history 336/week @ 2026-02-07 795/week @ 2026-02-14 1371/week @ 2026-02-21 1215/week @ 2026-02-28 1070/week @ 2026-03-07 1319/week @ 2026-03-14 939/week @ 2026-03-21 605/week @ 2026-03-28 1049/week @ 2026-04-04

4,083 downloads per month
Used in dbt-yaml

MIT/Apache

20KB
443 lines

dbt-yaml

Rust library for using the Serde serialization framework with data in YAML file format.

This is dbt Lab's fork of the original serde-yaml crate (https://github.com/dtolnay/serde-yaml), intended for use in dbt-fusion and other dbt projects.

Dependency

[dependencies]
serde = "1.0"
dbt-yaml = "1.0.1"

Release notes are available under GitHub releases.

Using dbt-yaml

API documentation is available in rustdoc form but the general idea is:

use std::collections::BTreeMap;

fn main() -> Result<(), dbt_yaml::Error> {
    // You have some type.
    let mut map = BTreeMap::new();
    map.insert("x".to_string(), 1.0);
    map.insert("y".to_string(), 2.0);

    // Serialize it to a YAML string.
    let yaml = dbt_yaml::to_string(&map)?;
    assert_eq!(yaml, "x: 1.0\ny: 2.0\n");

    // Deserialize it back to a Rust type.
    let deserialized_map: BTreeMap<String, f64> = dbt_yaml::from_str(&yaml)?;
    assert_eq!(map, deserialized_map);
    Ok(())
}

It can also be used with Serde's derive macros to handle structs and enums defined in your program.

[dependencies]
serde = { version = "1.0", features = ["derive"] }
dbt-serde_yaml = "0.0.1"

Structs serialize in the obvious way:

use serde::{Serialize, Deserialize};

#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Point {
    x: f64,
    y: f64,
}

fn main() -> Result<(), dbt_yaml::Error> {
    let point = Point { x: 1.0, y: 2.0 };

    let yaml = dbt_yaml::to_string(&point)?;
    assert_eq!(yaml, "x: 1.0\ny: 2.0\n");

    let deserialized_point: Point = dbt_yaml::from_str(&yaml)?;
    assert_eq!(point, deserialized_point);
    Ok(())
}

Enums serialize using YAML's !tag syntax to identify the variant name.

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, PartialEq, Debug)]
enum Enum {
    Unit,
    Newtype(usize),
    Tuple(usize, usize, usize),
    Struct { x: f64, y: f64 },
}

fn main() -> Result<(), dbt_yaml::Error> {
    let yaml = "
        - !Newtype 1
        - !Tuple [0, 0, 0]
        - !Struct {x: 1.0, y: 2.0}
    ";
    let values: Vec<Enum> = dbt_yaml::from_str(yaml).unwrap();
    assert_eq!(values[0], Enum::Newtype(1));
    assert_eq!(values[1], Enum::Tuple(0, 0, 0));
    assert_eq!(values[2], Enum::Struct { x: 1.0, y: 2.0 });

    // The last two in YAML's block style instead:
    let yaml = "
        - !Tuple
          - 0
          - 0
          - 0
        - !Struct
          x: 1.0
          y: 2.0
    ";
    let values: Vec<Enum> = dbt_yaml::from_str(yaml).unwrap();
    assert_eq!(values[0], Enum::Tuple(0, 0, 0));
    assert_eq!(values[1], Enum::Struct { x: 1.0, y: 2.0 });

    // Variants with no data can be written using !Tag or just the string name.
    let yaml = "
        - Unit  # serialization produces this one
        - !Unit
    ";
    let values: Vec<Enum> = dbt_yaml::from_str(yaml).unwrap();
    assert_eq!(values[0], Enum::Unit);
    assert_eq!(values[1], Enum::Unit);

    Ok(())
}

Code locations can be captured using the Spanned wrapper type.

use serde::{Serialize, Deserialize};
use dbt_yaml::Spanned;

#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Point {
    x: Spanned<f64>,
    y: Spanned<f64>,
}

fn main() -> Result<(), dbt_yaml::Error> {
    let yaml = "
        x: 1.0
        y: 2.0
    ";
    let point: Point = dbt_yaml::from_str(yaml)?;
    assert_eq!(*point.x, 2.0);
    assert_eq!(yaml[point.x.span().start.index..point.x.span().end.index].trim(), "1.0");
    assert_eq!(yaml[point.y.span().start.index..point.y.span().end.index].trim(), "2.0");
    Ok(())
}

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Dependencies

~135–520KB
~12K SLoC