Recursive AI

Merge or patch YAML

All oneyaml C# recipes

Overlay one document on another, or apply a JSON Patch, without losing the file’s comments and layout. A Merge Patch suits environment overrides; a JSON Patch suits scripted changes with a test guard.

C#
using OneYaml;
 
using var doc = YamlDocument.Parse("""
    # values.yaml
    image:
      repository: registry.example.com/web
      tag: "1.4.2"   # set by CI
    replicas: 2
    resources:
      limits:
        cpu: 500m
        memory: 256Mi
 
    """);
 
// An environment overlay as a merge patch: objects merge, null deletes.
doc.ApplyMergePatch("""{ "replicas": 5, "resources": { "limits": { "cpu": null, "memory": "1Gi" } } }""");
Console.Write(doc);
 
// A JSON Patch with a guard, built in code: `test` must pass or nothing changes.
var bump = new YamlPatch()
    .Test("/image/tag", "1.4.2")
    .Replace("/image/tag", "1.5.0");
doc.ApplyPatch(bump);
Console.WriteLine($"tag now {doc.Get<string>("/image/tag")}");
 
// Applied again, the test fails and the document is left as it was.
try
{
    doc.ApplyPatch(bump);
}
catch (YamlException e) when (e.Category == YamlErrorCategory.PatchTest)
{
    Console.WriteLine($"second run refused at operation {e.OperationIndex}: {e.Message}");
}
Text
# values.yaml
image:
  repository: registry.example.com/web
  tag: "1.4.2"   # set by CI
replicas: 5
resources:
  limits:
    memory: 1Gi
tag now 1.5.0
second run refused at operation 0: The value at '/image/tag' is not the value the test expects.

Good to know

  • Atomic. If any operation fails, the document is unchanged. The YamlException has a Category (PatchTest for a failed test) and an OperationIndex.
  • A Merge Patch merges mappings and replaces everything else. null deletes a key; a list in the patch replaces the whole list.
  • Only the named values change. The # set by CI comment and the quotes around the tag stay.
  • YAML rules, not JSON rules. test compares YAML values, so 1 and 1.0 differ. A value moved by move is written in the style of its new place, without its old comments.
  • ApplyPatch takes JSON text, UTF-8 bytes, a JsonNode or a YamlPatch; ApplyMergePatch takes JSON text, UTF-8 bytes or a JsonNode. All six operations are supported.

Every rule is in Patches.

A longer guide: Apply a JSON Patch to a YAML file.