yaml

package module
v0.0.9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 6, 2026 License: BSD-3-Clause, MIT Imports: 14 Imported by: 16

README

YAML marshaling and unmarshaling support for Go

Lint Test Go Go Report Card Latest Tag

Fork

This fork is an improved version of the invopop/yaml package, designed to include line and column location information for YAML elements during unmarshalling.

Origin tracking uses a two-pass approach:

  1. UnmarshalWithOriginTree decodes the YAML and extracts __origin__ metadata injected by the underlying oasdiff/yaml3 decoder, returning an *OriginTree alongside the decoded struct.
  2. The caller walks the OriginTree to apply file/line/column information to the decoded Go structs.

To decode without origin tracking, use Unmarshal as usual. To decode with origin tracking:

tree, err := yaml.UnmarshalWithOriginTree(data, &v, yaml.OriginOpt{Enabled: true, File: "myfile.yaml"})

The returned *OriginTree mirrors the YAML document structure. Each node holds a compact []any sequence with the file, key name, line, column, and locations of scalar fields and sequence items within that mapping. When Enabled is false, nil is returned for the tree with no overhead.

Introduction

A wrapper around go-yaml designed to enable a better way of handling YAML when marshaling to and from structs.

This is a fork and split of the original ghodss/yaml repository which no longer appears to be maintained.

In short, this library first converts YAML to JSON using go-yaml and then uses json.Marshal and json.Unmarshal to convert to or from the struct. This means that it effectively reuses the JSON struct tags as well as the custom JSON methods MarshalJSON and UnmarshalJSON unlike go-yaml. For a detailed overview of the rationale behind this method, see this blog post.

Compatibility

This package uses go-yaml and therefore supports everything go-yaml supports.

Tested against Go versions 1.14 and onwards.

Caveats

Caveat #1: When using yaml.Marshal and yaml.Unmarshal, binary data should NOT be preceded with the !!binary YAML tag. If you do, go-yaml will convert the binary data from base64 to native binary data, which is not compatible with JSON. You can still use binary in your YAML files though - just store them without the !!binary tag and decode the base64 in your code (e.g. in the custom JSON methods MarshalJSON and UnmarshalJSON). This also has the benefit that your YAML and your JSON binary data will be decoded exactly the same way. As an example:

BAD:
	exampleKey: !!binary gIGC

GOOD:
	exampleKey: gIGC
... and decode the base64 data in your code.

Caveat #2: When using YAMLToJSON directly, maps with keys that are maps will result in an error since this is not supported by JSON. This error will occur in Unmarshal as well since you can't unmarshal map keys anyways since struct fields can't be keys.

Installation and usage

To install, run:

$ go get github.com/invopop/yaml

And import using:

import "github.com/invopop/yaml"

Usage is very similar to the JSON library:

package main

import (
	"fmt"

	"github.com/invopop/yaml"
)

type Person struct {
	Name string `json:"name"` // Affects YAML field names too.
	Age  int    `json:"age"`
}

func main() {
	// Marshal a Person struct to YAML.
	p := Person{"John", 30}
	y, err := yaml.Marshal(p)
	if err != nil {
		fmt.Printf("err: %v\n", err)
		return
	}
	fmt.Println(string(y))
	/* Output:
	age: 30
	name: John
	*/

	// Unmarshal the YAML back into a Person struct.
	var p2 Person
	err = yaml.Unmarshal(y, &p2)
	if err != nil {
		fmt.Printf("err: %v\n", err)
		return
	}
	fmt.Println(p2)
	/* Output:
	{John 30}
	*/
}

yaml.YAMLToJSON and yaml.JSONToYAML methods are also available:

package main

import (
	"fmt"

	"github.com/invopop/yaml"
)

func main() {
	j := []byte(`{"name": "John", "age": 30}`)
	y, err := yaml.JSONToYAML(j)
	if err != nil {
		fmt.Printf("err: %v\n", err)
		return
	}
	fmt.Println(string(y))
	/* Output:
	name: John
	age: 30
	*/
	j2, err := yaml.YAMLToJSON(y)
	if err != nil {
		fmt.Printf("err: %v\n", err)
		return
	}
	fmt.Println(string(j2))
	/* Output:
	{"age":30,"name":"John"}
	*/
}

Documentation

Overview

Package yaml provides a wrapper around go-yaml designed to enable a better way of handling YAML when marshaling to and from structs.

In short, this package first converts YAML to JSON using go-yaml and then uses json.Marshal and json.Unmarshal to convert to or from the struct. This means that it effectively reuses the JSON struct tags as well as the custom JSON methods MarshalJSON and UnmarshalJSON unlike go-yaml.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func JSONToYAML

func JSONToYAML(j []byte) ([]byte, error)

JSONToYAML converts JSON to YAML.

func Marshal

func Marshal(o interface{}) ([]byte, error)

Marshal the object into JSON then converts JSON to YAML and returns the YAML.

func Unmarshal

func Unmarshal(y []byte, o interface{}, opts ...JSONOpt) error

Unmarshal converts YAML to JSON then uses JSON to unmarshal into an object, optionally configuring the behavior of the JSON unmarshal.

func YAMLToJSON

func YAMLToJSON(y []byte) ([]byte, error)

YAMLToJSON converts YAML to JSON. Since JSON is a subset of YAML, passing JSON through this method should be a no-op.

Things YAML can do that are not supported by JSON:

  • In YAML you can have binary and null keys in your maps. These are invalid in JSON. (int and float keys are converted to strings.)
  • Binary data in YAML with the !!binary tag is not supported. If you want to use binary data with this library, encode the data as base64 as usual but do not use the !!binary tag in your YAML. This will ensure the original base64 encoded data makes it all the way through to the JSON.

Types

type JSONOpt

type JSONOpt func(*json.Decoder) *json.Decoder

JSONOpt is a decoding option for decoding from JSON format.

type OriginOpt

type OriginOpt struct {
	// Enabled adds __origin__ metadata to maps during unmarshaling.
	Enabled bool
	// File is the source file name recorded in origin metadata.
	File string
}

OriginOpt controls origin-tracking behavior in UnmarshalWithOriginTree.

type OriginTree added in v0.0.6

type OriginTree struct {
	// File is the source file for all origins in this subtree.
	// Set once at the root of each decode call; all nodes in the same
	// decode share the same file.
	File string
	// Origin is the raw __origin__ value ([]any compact sequence) for this node.
	// Format: [key_name, key_line, key_col, nf, f1_name, f1_delta, f1_col, ..., ns, ...]
	Origin any
	// Fields holds child trees keyed by map key name.
	Fields map[string]*OriginTree
	// Items holds child trees for slice elements (index-aligned).
	Items []*OriginTree
}

OriginTree holds __origin__ data extracted from a YAML-decoded map tree. It mirrors the structure of the spec: Fields tracks map children by key, Items tracks slice children by index.

func UnmarshalWithOriginTree added in v0.0.6

func UnmarshalWithOriginTree(y []byte, o interface{}, origin OriginOpt, opts ...JSONOpt) (*OriginTree, error)

UnmarshalWithOriginTree is like UnmarshalWithOrigin but strips __origin__ from the intermediate map before JSON conversion and returns the extracted origin data as an OriginTree. The caller can apply the tree to Go structs after unmarshaling. When origin tracking is disabled, the returned tree is nil.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL