Table of Contents

Getting started

This page installs Bodu.Text.Yaml, runs a first round trip, renames members, and edits a document with the DOM. For the format specifics see the introduction; for the moving parts see core concepts.

Install

Bodu.Text.Yaml targets net8.0. Add the package:

dotnet add package Bodu.Text.Yaml

A first round trip

Serialize<T> writes an object graph to a YAML string; Deserialize<T> binds the text back to a type. Note that Deserialize<T> returns T?, so use ! where the document is known to be non-null:

using Bodu.Text.Yaml;

public sealed class ServerConfig
{
    public string Host { get; set; } = "";
    public int Port { get; set; }
}

var config = new ServerConfig { Host = "localhost", Port = 8080 };

string yaml = YamlSerializer.Serialize(config);
// Host: localhost
// Port: 8080

ServerConfig back = YamlSerializer.Deserialize<ServerConfig>(yaml)!;
// back.Port → 8080

Deserialize<T> also accepts UTF-8 bytes directly:

ReadOnlySpan<byte> utf8 = Encoding.UTF8.GetBytes(yaml);
ServerConfig fromBytes = YamlSerializer.Deserialize<ServerConfig>(utf8)!;

Deserialize<T>(Stream) and DeserializeAsync<T>(Stream) read a stream to its end, and Serialize<T>(IBufferWriter<byte>, …) / SerializeAsync<T>(Stream, …) write UTF-8 bytes. The stream overloads buffer the whole document in memory - only the stream copy is asynchronous.

Rename members

A naming policy renames every member; PropertyNameAttribute pins a single one and always wins over the policy:

using Bodu.Text.Serialization;
using Bodu.Text.Yaml;

public sealed class Endpoint
{
    [PropertyName("display-name")]
    public string DisplayName { get; set; } = "Health check";

    public int MaxRetryCount { get; set; } = 5;
}

var options = new YamlSerializerOptions
{
    PropertyNamingPolicy = NamingPolicy.SnakeCaseLower,
};

string yaml = YamlSerializer.Serialize(new Endpoint(), options);
// display-name: Health check
// max_retry_count: 5

The naming policies are CamelCase, SnakeCaseLower / SnakeCaseUpper, and KebabCaseLower / KebabCaseUpper; the YamlSerializerDefaults.Web preset selects camel-case with case-insensitive matching. Member shaping beyond renaming and ignoring is covered in Mapping attributes.

Edit a document without a model

When you do not have a POCO, parse to the mutable YamlNode DOM, index into the tree, build new scalars with YamlValue.Create(…), and write the document back with ToYamlString():

using Bodu.Text.Yaml.Nodes;

string source = """
    server:
      host: localhost
      port: 8080
    """;

YamlNode root = YamlNode.Parse(source)!;
root["server"]!["port"] = YamlValue.Create(9090);

string updated = root.ToYamlString();
// server:
//   host: localhost
//   port: 9090

YamlValue.Create has overloads for string, long, double, and bool. To read a value back out, use GetValue<T>() on a YamlValue.

Where to go next