Skip to content

Getting started

Install

go get gitlab.com/phpboyscout/go/yamldoc

Requires Go 1.26+. The library has one dependency, goccy/go-yaml.

Change a value

yamldoc works on bytes. It never touches the filesystem, so you read and write the file yourself — which means it works equally well over an in-memory filesystem, an object store, or a git worktree.

package main

import (
    "fmt"
    "os"

    "gitlab.com/phpboyscout/go/yamldoc"
)

func main() {
    src, err := os.ReadFile("config.yaml")
    if err != nil {
        panic(err)
    }

    f, err := yamldoc.Parse(src)
    if err != nil {
        panic(err)
    }

    if err := f.Documents()[0].Set("server.port", 9090); err != nil {
        panic(err)
    }

    out, err := f.Bytes()
    if err != nil {
        panic(err)
    }

    fmt.Print(string(out))
}

Given this input:

server:
  host: localhost   # where we bind
  port: 8080

you get exactly this — one line different, comment intact:

server:
  host: localhost # where we bind
  port: 9090

Check before you edit

A few YAML constructs cannot be round-tripped safely. yamldoc detects them and reports them rather than silently producing a damaged document — but it is your decision what to do about it.

if u := f.Unsupported(); len(u) > 0 {
    return fmt.Errorf("cannot safely edit %s: %s", path, u[0])
}

Emitting a file that contains one returns ErrUnsupported rather than bytes, so you cannot write a broken document by forgetting to check. See Refuse unsafe documents.

Read before you write

n, ok := f.Documents()[0].Get("server.host")
if ok {
    fmt.Println(n.String())          // localhost
    fmt.Println(n.Position().Line)   // 2
    fmt.Println(n.Comments().Line)   // where we bind
}

Next