Recursive AI

Switch from yaml.v3 with one import

All oneyaml Go recipes

oneyaml.dev/go/compat/yamlv3 is an adapter for the common API of gopkg.in/yaml.v3: Unmarshal, Marshal, Decoder, Encoder and yaml.Node with its comments. Change the import path and your call sites stay; the package name is still yaml.

GO
// before
import "gopkg.in/yaml.v3"
 
// after
import yaml "oneyaml.dev/go/compat/yamlv3"
GO
package main
 
import (
	"fmt"
	"log"
 
	yaml "oneyaml.dev/go/compat/yamlv3" // was: yaml "gopkg.in/yaml.v3"
)
 
type Config struct {
	Name    string   `yaml:"name"`
	Enabled bool     `yaml:"enabled"`
	Tags    []string `yaml:"tags"`
}
 
func main() {
	// The same calls as yaml.v3: Unmarshal, Marshal, yaml.Node.
	var cfg Config
	if err := yaml.Unmarshal([]byte("name: web\nenabled: true\ntags: [a, b]\n"), &cfg); err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%+v\n", cfg)
 
	out, err := yaml.Marshal(cfg)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Print(string(out))
 
	// Comments on yaml.Node, as in yaml.v3.
	var n yaml.Node
	if err := yaml.Unmarshal([]byte("# owner: platform\nname: web # the service\n"), &n); err != nil {
		log.Fatal(err)
	}
	m := n.Content[0]
	fmt.Printf("key head comment %q, value line comment %q\n", m.Content[0].HeadComment, m.Content[1].LineComment)
}
Text
{Name:web Enabled:true Tags:[a b]}
name: web
enabled: true
tags:
    - a
    - b
key head comment "# owner: platform", value line comment "# the service"

Good to know

  • The adapter reads YAML 1.1 forms the way yaml.v3 does, so existing files mean what they meant. New code should use the oneyaml package, which reads YAML 1.2.
  • Known differences: a 3.5 read into an integer field is a type error instead of being truncated; invalid YAML that yaml.v3 accepts is refused; and where yaml.v3 panics, the adapter returns an error.
  • An UnmarshalYAML that takes gopkg.in/yaml.v3’s own *yaml.Node, in a type from another module, can’t be called by the adapter, so reading into that type is an error that names it. The migration guide shows how to wrap it.
  • The adapter always runs with the default limits and has no Untrusted() mode. Bound the input size yourself.
  • For sigs.k8s.io/yaml, the adapter is oneyaml.dev/go/compat/k8syaml (migration guide).

The checklist and every difference are in Migrating from yaml.v3.

A longer guide to the four routes off the archived module: yaml.v3 is archived: what to use instead.