#serde-yaml #serde #serialization #deserialize #serde-derive

bin+lib serde_yml

A robust Rust library that simplifies the serialization and deserialization of Rust data structures to and from YAML format using the widely-used Serde framework

4 releases

0.0.4 Apr 3, 2024
0.0.3 Apr 1, 2024
0.0.2 Mar 29, 2024
0.0.1 Mar 29, 2024

#143 in Encoding

Download history 456/week @ 2024-03-27 299/week @ 2024-04-03 162/week @ 2024-04-10 264/week @ 2024-04-17

1,181 downloads per month
Used in 4 crates

MIT/Apache

445KB
10K SLoC

Serde YML logo

Serde YML: Seamless YAML Serialization for Rust

Serde YML is a Rust library that simplifies YAML serialization and deserialization using Serde. Effortlessly convert Rust types to YAML and vice versa. Supports custom structs, enums, and error handling.

Banner of Serde YML

Made With Rust Crates.io Lib.rs Docs.rs License Codecov

WebsiteDocumentationReport BugRequest FeatureContributing Guidelines

Overview

Serde YML is a robust Rust library that simplifies the serialization and deserialization of Rust data structures to and from YAML format using the widely-used Serde framework. With Serde YML, you can effortlessly convert your Rust types into YAML strings and vice versa, streamlining the process of storing, transmitting, and manipulating structured data.providing style guides for your library.

Features

  • Serialize Rust data structures to YAML format
  • Deserialize YAML data into Rust types
  • Support for custom structs and enums using Serde's derive macros
  • Handling of YAML's !tag syntax for representing enum variants
  • Direct access to YAML values through the Value type and related types
  • Comprehensive error handling with Error, Location, and Result types
  • Well-documented with examples and explanations

Usage

Serde YML offers a straightforward and intuitive API for working with YAML data in Rust. Here's a quick example of how to serialize and deserialize a Rust type:

use serde::{Serialize, Deserialize};

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

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

    // Serialize to YAML
    let yaml = serde_yml::to_string(&point)?;
    assert_eq!(yaml, "x: 1.0\ny: 2.0\n");

    // Deserialize from YAML
    let deserialized_point: Point = serde_yml::from_str(&yaml)?;
    assert_eq!(point, deserialized_point);

    Ok(())
}

Examples

To get started with Serde YML, you can use the examples provided in the examples directory of the project.

Serde YML provides a set of comprehensive examples to demonstrate its usage and capabilities.

To run the examples, clone the repository and run the following command in your terminal from the project root directory.

cargo run --example example

The command will execute the example code, demonstrating various features and use cases of the Serde YML library. The examples cover various scenarios, including serializing and deserializing structs, enums, optional fields, custom structs, and more.

Here are a few notable examples:

Serializing and Deserializing Structs

use serde::{Serialize, Deserialize};
use serde_yml;

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

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

    // Serialize to YAML
    let yaml = serde_yml::to_string(&point)?;
    assert_eq!(yaml, "x: 1.0\ny: 2.0\n");

    // Deserialize from YAML
    let deserialized_point: Point = serde_yml::from_str(&yaml)?;
    assert_eq!(point, deserialized_point);

    Ok(())
}

Serializing and Deserializing Enums

use serde::{Serialize, Deserialize};
use serde_yml;

#[derive(Serialize, Deserialize, PartialEq, Debug)]
enum Shape {
    Rectangle { width: u32, height: u32 },
    Circle { radius: f64 },
    Triangle { base: u32, height: u32 },
}

fn main() -> Result<(), serde_yml::Error> {
    let shapes = vec![
        Shape::Rectangle { width: 10, height: 20 },
        Shape::Circle { radius: 5.0 },
        Shape::Triangle { base: 8, height: 12 },
    ];

    // Serialize to YAML
    let yaml = serde_yml::to_string(&shapes)?;
    println!("Serialized YAML:\n{}", yaml);

    // Deserialize from YAML
    let deserialized_shapes: Vec<Shape> = serde_yml::from_str(&yaml)?;
    assert_eq!(shapes, deserialized_shapes);

    Ok(())
}

Serializing and Deserializing Optional Fields

use serde::{Serialize, Deserialize};
use serde_yml;

#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct User {
    name: String,
    age: Option<u32>,
    #[serde(default)]
    is_active: bool,
}

fn main() -> Result<(), serde_yml::Error> {
    let user = User {
        name: "John".to_string(),
        age: Some(30),
        is_active: true,
    };

    // Serialize to YAML
    let yaml = serde_yml::to_string(&user)?;
    println!("Serialized YAML:\n{}", yaml);

    // Deserialize from YAML
    let deserialized_user: User = serde_yml::from_str(&yaml)?;
    assert_eq!(user, deserialized_user);

    Ok(())
}

Serializing and Deserializing a HashMap

use std::collections::HashMap;

fn main() -> Result<(), serde_yml::Error> {
  let mut map = HashMap::new();
  map.insert("name".to_string(), &"John");
  map.insert("age".to_string(), &"30");

  let yaml = serde_yml::to_string(&map)?;
  println!("Serialized YAML: {}", yaml);

  let deserialized_map: HashMap<String, serde_yml::Value> = serde_yml::from_str(&yaml)?;
   println!("Deserialized map: {:?}", deserialized_map);

   Ok(())
}

Serializing and Deserializing Custom Structs

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]
struct Person {
    name: String,
    age: u32,
    city: String,
}

fn main() -> Result<(), serde_yml::Error> {
  let person = Person {
      name: "Alice".to_string(),
      age: 25,
      city: "New York".to_string(),
  };

  let yaml = serde_yml::to_string(&person)?;
  println!("Serialized YAML: {}", yaml);

  let deserialized_person: Person = serde_yml::from_str(&yaml)?;
  println!("Deserialized person: {:?}", deserialized_person);

  Ok(())
}

Using Serde derive

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

Structs serialize in the obvious way:

# use serde_derive::{Serialize, Deserialize};

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

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

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

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

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

use serde_derive::{Serialize, Deserialize};

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

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

    Ok(())
}

Best Practices and Common Pitfalls

  • When serializing large datasets, consider using serde_yml::to_writer to write the YAML output directly to a file or a writer instead of keeping the entire serialized string in memory.
  • Be cautious when deserializing untrusted YAML input, as it may contain unexpected or malicious data. Always validate and handle the deserialized data appropriately.
  • When working with custom structs or enums, ensure that they implement the necessary Serde traits (Serialize and Deserialize) for proper serialization and deserialization.
  • If you encounter any issues or have questions, refer to the library's documentation and examples for guidance. If the problem persists, consider opening an issue on the library's GitHub repository.

Installation

To use Serde YML in your Rust project, add the following to your Cargo.toml file:

[dependencies]
serde_yml = "0.0.4"

Semantic Versioning Policy

For transparency into our release cycle and in striving to maintain backward compatibility, serde_yml follows semantic versioning.

License

The project is licensed under the terms of both the MIT license and the Apache License (Version 2.0).

Contribution

We welcome all people who want to contribute. Please see the contributing instructions for more information.

Contributions in any form (issues, pull requests, etc.) to this project must adhere to the Rust's Code of Conduct.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Acknowledgements

A big thank you to all the awesome contributors of serde_yml for their help and support. A special thank you goes to David Tolnay and his work on Serde YAML for inspiring this project.

Dependencies

~10–24MB
~296K SLoC