Documentation
¶
Overview ¶
Package yaml reads and writes YAML documents.
Marshal and Unmarshal cover the ordinary case, as in the standard library's encoding packages, and take no option. Anything else lives a layer down:
- codec holds Encoder and Decoder, the twenty-six options that steer them, MapSlice, RawMessage, and the comment types. Use codec.NewDecoder to read a stream and codec.UnmarshalWithOptions to pass an option.
- github.com/go-openapi/go-yaml/ast holds the document as a tree.
- github.com/go-openapi/go-yaml/parser builds that tree from a source, and github.com/go-openapi/go-yaml/parser/scanner hands it the tokens.
- github.com/go-openapi/go-yaml/errors declares the failure every one of them reports, with the position it happened at.
- github.com/go-openapi/go-yaml/expressions navigates a document by path.
Tags ¶
A tag is read by the URI it names rather than by the shorthand it was written with, so "!!int", "!<tag:yaml.org,2002:int>" and "!e!int" under "%TAG !e! tag:yaml.org,2002:" are one tag. The expansion is on the node, at github.com/go-openapi/go-yaml/ast.TagNode.URI.
The seven tags of the YAML 1.2 core schema (§10.2) are resolved: !!null, !!bool, !!int, !!float, !!str, !!seq and !!map.
Five more come from the 1.1 type repository at https://yaml.org/type and are resolved as well, under either version:
- !!binary decodes base64 into []byte, and a text base64 cannot read is an error.
- !!merge is the "<<" key, whose mapping's entries are folded into the one holding it.
- !!omap has to stand on a sequence and decodes as one, in the order it was written. There is no ordered-map type behind it; use codec.UseOrderedMap to get codec.MapSlice for every mapping.
- !!set has to stand on a mapping and decodes as a map with nil values.
- !!timestamp decodes to a time.Time, and a text no format reads is an error. The formats are the ones yaml.org/type/timestamp.html spells.
!!timestamp takes two rules, since YAML 1.2 has no timestamp of its own and other libraries differ. An explicit !!timestamp resolves whatever version the document declares, because a tag names a URI and is not resolution. An untagged "2001-12-14" is a string in both versions, and only a Go field of type time.Time asks for the conversion -- go.yaml.in/yaml/v3 reads it as a time.Time and gopkg.in/yaml.v2 as a string. github.com/go-openapi/go-yaml/parser.WithYAMLVersion and a "%YAML" directive select what an untagged plain scalar resolves to, and neither changes what a tag means.
Three tags of the 1.1 repository are not resolved: !!pairs, !!value and !!yaml. They are parsed and carried on the node like any other tag, and the value under them stands as it was written. So does every tag outside these fifteen -- a local "!thing", a handle a "%TAG" line declared, another namespace -- with one rule: a tag nothing resolves leaves its scalar as text, digits and all, so "!thing 12" is the string "12". §6.9.1 hands a local tag to the application, so none of these is an error.
A tag naming a type its scalar is not ¶
"!!int abc" is an assertion that does not hold, and by default it is an error naming both: cannot read "abc" as !!int. The same goes for !!bool, !!float, !!null, !!binary and !!timestamp.
YAML leaves this open. §3.1.2 builds a representation from the serialization, and a node whose tag will not apply has none to build; what a processor then owes the caller is not stated, so refusing, zeroing and echoing the text are all conformant. This library refused three of the six and answered the other three with a zero until 2026-09-07, which meant a caller could not tell "!!int abc" from a written 0.
github.com/go-openapi/go-yaml/parser.WithLaxTags reads the text instead, so "!!int abc" is the string "abc". The tag stays on the node either way and a render writes it back, so a document read laxly still round-trips.
Two things stay strict. A tag naming a kind its node is not -- "!!seq 5" -- is reported whatever the policy, since no text stands in for a sequence. And a tag the YAML 1.2 grammar has no production for, such as "!<>" or "!!<x>", is refused as the document is scanned.
The verdict is the node's own, at github.com/go-openapi/go-yaml/ast.TagNode.Resolve, so every consumer of one tree gives one answer: Unmarshal, codec.ToJSON and a caller holding a single node all read it there.
Anchors and aliases ¶
An alias builds its own value. "first: *b" and "second: *b" give two maps, so a caller writing through one leaves the other alone, and a document naming far more than it holds -- 259 bytes of nested aliases name 100,000 values -- is refused with github.com/go-openapi/go-yaml/errors.ErrExcessiveAliasing rather than built.
codec.ShareAliases hands every alias of one anchor the same value instead. Ask for it when the anchors have to survive a round trip through a Go value: codec.MarshalAnchor, codec.WithSmartAnchor and the ",anchor" and ",alias" struct tags find an anchor by the address its value stands at, so an encoder can write "*name" only where the decode left one value under two names. Reading a document into an github.com/go-openapi/go-yaml/ast tree and rendering it keeps the anchors either way; this is about the Go value.
Sharing was the default until 2026-09-07, and whether it applied turned on whether the destination happened to declare a field for the anchor itself.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Marshal ¶
Marshal serializes v into a YAML document.
See codec.Marshal for how a Go value is mapped onto YAML and what the struct tags mean.
Example ¶
package main
import (
"bytes"
"fmt"
"strconv"
"github.com/go-openapi/go-yaml"
"github.com/go-openapi/go-yaml/codec"
)
type SlowMarshaler struct {
A string
B int
}
type FastMarshaler struct {
A string
B int
}
type TextMarshaler int64
type TextMarshalerContainer struct {
Field TextMarshaler `yaml:"field"`
}
func (v SlowMarshaler) MarshalYAML() ([]byte, error) {
var buf bytes.Buffer
buf.WriteString("tags:\n")
buf.WriteString("- slow-marshaler\n")
buf.WriteString("a: " + v.A + "\n")
buf.WriteString("b: " + strconv.FormatInt(int64(v.B), 10) + "\n")
return buf.Bytes(), nil
}
func (v FastMarshaler) MarshalYAML() (interface{}, error) {
return codec.MapSlice{
{Key: "tags", Value: []string{"fast-marshaler"}},
{Key: "a", Value: v.A},
{Key: "b", Value: v.B},
}, nil
}
func (t TextMarshaler) MarshalText() ([]byte, error) {
return []byte(strconv.FormatInt(int64(t), 8)), nil
}
func main() {
var slow SlowMarshaler
slow.A = "Hello slow poke"
slow.B = 100
buf, err := yaml.Marshal(slow)
if err != nil {
panic(err.Error())
}
fmt.Println(string(buf))
var fast FastMarshaler
fast.A = "Hello speed demon"
fast.B = 100
buf, err = yaml.Marshal(fast)
if err != nil {
panic(err.Error())
}
fmt.Println(string(buf))
text := TextMarshalerContainer{
Field: 11,
}
buf, err = yaml.Marshal(text)
if err != nil {
panic(err.Error())
}
fmt.Println(string(buf))
}
Output: tags: - slow-marshaler a: Hello slow poke b: 100 tags: - fast-marshaler a: Hello speed demon b: 100 field: "13"
Example (ExplicitAnchorAlias) ¶
package main
import (
"fmt"
"github.com/go-openapi/go-yaml"
)
func main() {
type T struct {
A int
B string
}
var v struct {
C *T `yaml:"c,anchor=x"`
D *T `yaml:"d,alias=x"`
}
v.C = &T{A: 1, B: "hello"}
v.D = v.C
bytes, err := yaml.Marshal(v)
if err != nil {
panic(err)
}
fmt.Println(string(bytes))
}
Output: c: &x a: 1 b: hello d: *x
Example (ImplicitAnchorAlias) ¶
package main
import (
"fmt"
"github.com/go-openapi/go-yaml"
)
func main() {
type T struct {
I int
S string
}
var v struct {
A *T `yaml:"a,anchor"`
B *T `yaml:"b,anchor"`
C *T `yaml:"c"`
D *T `yaml:"d"`
}
v.A = &T{I: 1, S: "hello"}
v.B = &T{I: 2, S: "world"}
v.C = v.A // C has same pointer address to A
v.D = v.B // D has same pointer address to B
bytes, err := yaml.Marshal(v)
if err != nil {
panic(err)
}
fmt.Println(string(bytes))
}
Output: a: &a i: 1 s: hello b: &b i: 2 s: world c: *a d: *b
Example (Node) ¶
package main
import (
"fmt"
"github.com/go-openapi/go-yaml"
"github.com/go-openapi/go-yaml/ast"
"github.com/go-openapi/go-yaml/codec"
)
func main() {
type T struct {
Text ast.Node `yaml:"text"`
}
stringNode, err := codec.ValueToNode("node example")
if err != nil {
panic(err)
}
bytes, err := yaml.Marshal(T{Text: stringNode})
if err != nil {
panic(err)
}
fmt.Println(string(bytes))
}
Output: text: node example
func Unmarshal ¶
Unmarshal decodes the YAML document data into the value pointed to by v.
See codec.Unmarshal for how a YAML document is mapped onto a Go value.
Example (JSONTags) ¶
package main
import (
"fmt"
"log"
"github.com/go-openapi/go-yaml"
)
func main() {
yml := `---
foo: 1
bar: c
`
var v struct {
A int `json:"foo"`
B string `json:"bar"`
}
if err := yaml.Unmarshal([]byte(yml), &v); err != nil {
log.Fatal(err)
}
fmt.Println(v.A)
fmt.Println(v.B)
}
Output: 1 c
Example (YAMLTags) ¶
package main
import (
"fmt"
"log"
"github.com/go-openapi/go-yaml"
)
func main() {
yml := `---
foo: 1
bar: c
A: 2
B: d
`
var v struct {
A int `yaml:"foo" json:"A"`
B string `yaml:"bar" json:"B"`
}
if err := yaml.Unmarshal([]byte(yml), &v); err != nil {
log.Fatal(err)
}
fmt.Println(v.A)
fmt.Println(v.B)
}
Output: 1 c
Types ¶
This section is empty.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package conformance measures this parser against the YAML Test Suite.
|
Package conformance measures this parser against the YAML Test Suite. |
|
Package errors reports what went wrong reading or writing a YAML document, with the position it happened at and the lines of source around it.
|
Package errors reports what went wrong reading or writing a YAML document, with the position it happened at and the lines of source around it. |
|
internal
|
|
|
corpus
Package corpus generates the synthetic documents the benchmarks run on.
|
Package corpus generates the synthetic documents the benchmarks run on. |
|
fuzzseeds
Package fuzzseeds supplies the shared seed corpus for the fuzz targets.
|
Package fuzzseeds supplies the shared seed corpus for the fuzz targets. |
|
lab
Package lab holds parsers we are experimenting on.
|
Package lab holds parsers we are experimenting on. |
|
nocopy
Package nocopy makes a string that shares a byte slice's memory.
|
Package nocopy makes a string that shares a byte slice's memory. |
|
probe
Package probe counts what the library did, for tests that ask a question no output answers.
|
Package probe counts what the library did, for tests that ask a question no output answers. |
|
refparser
Package refparser is the parser this library shipped before the token tape, kept as the yardstick the current one is measured against.
|
Package refparser is the parser this library shipped before the token tape, kept as the yardstick the current one is measured against. |
|
scanner
Package scanner turns the bytes of a YAML stream into tokens.
|
Package scanner turns the bytes of a YAML stream into tokens. |
|
scanner/internal/testscanner
Package testscanner provide testing utilities to the scanner package.
|
Package testscanner provide testing utilities to the scanner package. |
|
scanner/swar
Package swar scans eight bytes of a document at a time, in one register.
|
Package swar scans eight bytes of a document at a time, in one register. |
|
tokenarena
Package tokenarena holds the tokens of a parse in chunks it can reuse.
|
Package tokenarena holds the tokens of a parse in chunks it can reuse. |
|
analysis
module
|
|
|
This source inspired by https://github.com/fatih/color.
|
This source inspired by https://github.com/fatih/color. |