Serde YML (a fork of Serde YAML)
A Rust library for using the Serde serialization framework with data in
YAML file format. This project, has been renamed to Serde YML to
avoid confusion with the original Serde YAML crate which is now archived and
no longer maintained.
Credits and Acknowledgements
This library is a continuation of the excellent work done by David Tolnay
and the maintainers of the serde-yaml library.
While Serde YML started as a fork of serde-yaml, it has now evolved into a
separate library with its own goals and direction in mind and does not intend
to replace the original serde-yaml crate.
If you are currently using serde-yaml in your projects, we recommend carefully
evaluating your requirements and considering the stability and maturity of the
original library as well as looking at the features and improvements offered by
other YAML libraries in the Rust ecosystem.
I would like to express my sincere gratitude to David Tolnay and the
serde-yaml team for their valuable contributions to the Rust community
and for inspiring this project.
Dependency
[dependencies]
serde = "1.0"
serde_yml = "0.0.11"
Release notes are available under GitHub releases.
Using Serde YML
API documentation is available in rustdoc form but the general idea
is:
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 };
let yaml = serde_yml::to_string(&point)?;
assert_eq!(yaml, "x: 1.0\ny: 2.0\n");
let deserialized_point: Point = serde_yml::from_str(&yaml)?;
assert_eq!(point, deserialized_point);
Ok(())
}
Examples
Serde YML provides a set of comprehensive examples. You can find them in the
examples
directory of the project. To run the examples, clone the repository
and execute the following command in your terminal from the project:
cargo run --example example
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 };
let yaml = serde_yml::to_string(&point)?;
assert_eq!(yaml, "x: 1.0\ny: 2.0\n");
let deserialized_point: Point = serde_yml::from_str(&yaml)?;
assert_eq!(point, deserialized_point);
Ok(())
}
This example demonstrates how to serialize and deserialize a simple struct
Point
to and from YAML using the serde_yml
crate.
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 },
];
let yaml = serde_yml::to_string(&shapes)?;
println!("Serialized YAML:\n{}", yaml);
let deserialized_shapes: Vec<Shape> = serde_yml::from_str(&yaml)?;
assert_eq!(shapes, deserialized_shapes);
Ok(())
}
This example demonstrates how to serialize and deserialize an enum Shape
(with struct variants) to and from YAML using the serde_yml
crate.
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,
};
let yaml = serde_yml::to_string(&user)?;
println!("Serialized YAML:\n{}", yaml);
let deserialized_user: User = serde_yml::from_str(&yaml)?;
assert_eq!(user, deserialized_user);
Ok(())
}
This example demonstrates how to serialize and deserialize a struct User
with
an optional field age
to and from YAML using the serde_yml
crate.
Serializing and Deserializing a HashMap
use std::collections::HashMap;
use serde_yml;
fn main() -> Result<(), serde_yml::Error> {
let mut map = HashMap::new();
map.insert("name".to_string(), "John".to_string());
map.insert("age".to_string(), "30".to_string());
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(())
}
This example demonstrates how to serialize and deserialize a HashMap
to and
from YAML using the serde_yml
crate.
Serializing and Deserializing Custom Structs
use serde::{Serialize, Deserialize};
use serde_yml;
#[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(())
}
This example demonstrates how to serialize and deserialize a custom struct
Person
to and from YAML using the serde_yml
crate.
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};
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 };
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};
use serde_yml;
#[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 });
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 });
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(())
}
This example demonstrates how to use Serde's derive macros to automatically
implement the Serialize
and Deserialize
traits for a struct Point
, and
then serialize and deserialize it to and from YAML using the serde_yml
crate.
Serializing and Deserializing Enums with Custom Serialization and Deserialization
use serde::{Deserialize, Serialize};
use serde::de::{self, Deserializer, MapAccess, Visitor};
use serde::ser::{SerializeMap, Serializer};
use std::fmt;
use serde_yml;
#[derive(Serialize, Deserialize, PartialEq, Debug)]
enum MyEnum {
Variant1(String),
Variant2 { field: i32 },
}
#[derive(PartialEq, Debug)]
struct MyStruct {
field: MyEnum,
}
fn main() -> Result<(), serde_yml::Error> {
let input = MyStruct {
field: MyEnum::Variant2 { field: 42 },
};
let yaml = serde_yml::to_string(&input).unwrap();
println!("\n✅ Serialized YAML:\n{}", yaml);
let output: MyStruct = serde_yml::from_str(&yaml).unwrap();
println!("\n✅ Deserialized YAML:\n{:#?}", output);
assert_eq!(input, output);
Ok(())
}
This example demonstrates how to use custom Serialize
and Deserialize
implementations for a struct containing an enum field, and how to leverage
serde_yml
to serialize and deserialize the struct to and from YAML.
Serializing and Deserializing Optional Enums
use serde::{Deserialize, Serialize};
use serde_yml;
use serde_yml::with::singleton_map_optional;
#[derive(Serialize, Deserialize, PartialEq, Debug)]
enum OptionalEnum {
Variant1(String),
Variant2 { field: i32 },
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct OptionalStruct {
#[serde(with = "singleton_map_optional")]
field: Option<OptionalEnum>,
}
fn main() -> Result<(), serde_yml::Error> {
let input = OptionalStruct {
field: Some(OptionalEnum::Variant2 { field: 42 }),
};
let yaml = serde_yml::to_string(&input).unwrap();
println!("\n✅ Serialized YAML:\n{}", yaml);
let output: OptionalStruct = serde_yml::from_str(&yaml).unwrap();
println!("\n✅ Deserialized YAML:\n{:#?}", output);
assert_eq!(input, output);
Ok(())
}
This example demonstrates how to use the singleton_map_optional
attribute to serialize and deserialize an Option<Enum>
field as a single
YAML mapping entry with the key being the enum variant name.
Serializing and Deserializing Nested Enums
use serde::{Deserialize, Serialize};
use serde_yml;
use serde_yml::with::singleton_map_recursive;
#[derive(Serialize, Deserialize, PartialEq, Debug)]
enum NestedEnum {
Variant1(String),
Variant2(Option<InnerEnum>),
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
enum InnerEnum {
Inner1(i32),
Inner2(i32),
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct NestedStruct {
#[serde(with = "singleton_map_recursive")]
field: NestedEnum,
}
fn main() -> Result<(), serde_yml::Error> {
let input = NestedStruct {
field: NestedEnum::Variant2(Some(InnerEnum::Inner2(42))),
};
let yaml = serde_yml::to_string(&input).unwrap();
println!("\n✅ Serialized YAML:\n{}", yaml);
let output: NestedStruct = serde_yml::from_str(&yaml).unwrap();
println!("\n✅ Deserialized YAML:\n{:#?}", output);
assert_eq!(input, output);
Ok(())
}
This example demonstrates how to use the singleton_map_recursive
attribute to
serialize and deserialize a nested enum structure where one of the enum
variants contains an optional inner enum.
Serializing and Deserializing Enums with singleton_map_recursive
use serde::{Deserialize, Serialize};
use serde_yml;
use serde_yml::with::singleton_map_recursive;
#[derive(Serialize, Deserialize, PartialEq, Debug)]
enum MyEnum {
Variant1(String),
Variant2 { field: i32 },
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct MyStruct {
#[serde(with = "singleton_map_recursive")]
field: MyEnum,
}
fn main() -> Result<(), serde_yml::Error> {
let input = MyStruct {
field: MyEnum::Variant2 { field: 42 },
};
let yaml = serde_yml::to_string(&input).unwrap();
println!("\n✅ Serialized YAML:\n{}", yaml);
let output: MyStruct = serde_yml::from_str(&yaml).unwrap();
println!("\n✅ Deserialized YAML:\n{:#?}", output);
assert_eq!(input, output);
Ok(())
}
This example demonstrates how to use the singleton_map_recursive
attribute to
serialize and deserialize an enum field as a single YAML mapping entry with the
key being the enum variant name.
Serializing and Deserializing Enums with singleton_map_with
and Custom Serialization
use serde::{Deserialize, Serialize};
use serde_yml;
use serde_yml::with::singleton_map_with;
fn custom_serialize<T, S>(
value: &T,
serializer: S,
) -> Result<S::Ok, S::Error>
where
T: Serialize,
S: serde::Serializer,
{
singleton_map_with::serialize(value, serializer)
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
enum MyEnum {
Variant1(String),
Variant2 { field: i32 },
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct MyStruct {
#[serde(
serialize_with = "custom_serialize",
deserialize_with = "singleton_map_with::deserialize"
)]
field: MyEnum,
}
fn main() -> Result<(), serde_yml::Error> {
let input = MyStruct {
field: MyEnum::Variant2 { field: 42 },
};
let yaml = serde_yml::to_string(&input).unwrap();
println!("\n✅ Serialized YAML:\n{}", yaml);
let output: MyStruct = serde_yml::from_str(&yaml).unwrap();
println!("\n✅ Deserialized YAML:\n{:#?}", output);
assert_eq!(input, output);
Ok(())
}
This example demonstrates how to use the singleton_map_with
attribute in
combination with a custom serialization function (custom_serialize
) to
serialize and deserialize an enum field (MyEnum
) within a struct
(MyStruct
).
The custom_serialize
function is used for serialization, while the
singleton_map_with::deserialize
function is used for deserialization. This
allows for additional customization of the serialization process while still
leveraging the singleton_map_with attribute for deserialization.
Serializing and Deserializing Enums with singleton_map_with
use serde::{Deserialize, Serialize};
use serde_yml;
use serde_yml::with::singleton_map_with;
#[derive(Serialize, Deserialize, PartialEq, Debug)]
enum MyEnum {
Variant1(String),
Variant2 { field: i32 },
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct MyStruct {
#[serde(with = "singleton_map_with")]
field: MyEnum,
}
fn main() -> Result<(), serde_yml::Error> {
let input = MyStruct {
field: MyEnum::Variant2 { field: 42 },
};
let yaml = serde_yml::to_string(&input).unwrap();
println!("\n✅ Serialized YAML:\n{}", yaml);
let output: MyStruct = serde_yml::from_str(&yaml).unwrap();
println!("\n✅ Deserialized YAML:\n{:#?}", output);
assert_eq!(input, output);
Ok(())
}
This example demonstrates how to use the singleton_map_with
attribute to
serialize and deserialize an enum field (MyEnum
) within a struct
(MyStruct
). The singleton_map_with
attribute allows for additional
customization of the serialization and deserialization process through the use
of helper functions.
License
Licensed under either of the Apache License or the
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.