Recursive AI

Read YAML without a class

All oneyaml C# recipes

When you don’t have a type for the data, parse it into a YamlDocument and read values by JSON Pointer, or walk its nodes the way you walk a JsonNode.

C#
using OneYaml;
 
using var doc = YamlDocument.Parse("""
    server:
      host: 0.0.0.0
      port: 8080   # behind the load balancer
    features: [auth, metrics]
    limits:
      cpu: 0.5
      memory: 512Mi
    """);
 
// Read one value into a .NET type, by JSON Pointer.
Console.WriteLine($"port: {doc.Get<int>("/server/port")}");
 
// Or walk the nodes, like JsonNode: values, kinds and positions.
YamlNode port = doc.Root["server"]["port"];
Console.WriteLine($"port {port.GetValue<int>()} at {port.Position.Line}:{port.Position.Column}");
 
foreach (YamlNode feature in doc.Root["features"].Items)
{
    Console.WriteLine($"feature: {feature.GetValue<string>()}");
}
foreach (var (key, value) in doc.Root["limits"].Entries)
{
    Console.WriteLine($"limit {key.GetValue<string>()} = {value.GetValue<string>()} ({value.Kind})");
}
 
// A missing path: check first, or use TryGet.
Console.WriteLine(doc.Contains("/server/tls"));
Console.WriteLine(doc.TryGet("/server/tls", out bool tls) ? $"tls: {tls}" : "tls not set");
Text
port: 8080
port 8080 at 3:9
feature: auth
feature: metrics
limit cpu = 0.5 (Scalar)
limit memory = 512Mi (Scalar)
False
tls not set

Good to know

  • doc.Get<T>(pointer) reads the node at a JSON Pointer into any type, with the serializer’s rules. TryGet and Contains check without throwing.
  • node["key"] and node[0] index mappings and sequences. Items and Entries enumerate them in file order.
  • Position is where the node’s content starts: a 1-based line and column, and the offset.
  • Kind, Style, Tag and Anchor describe the node as written. GetValue<T> reads a scalar; Deserialize<T> reads a whole subtree.
  • Every pointer method takes a document index for multi-document files, 0 by default (multi-document files).