Documentation
¶
Overview ¶
Package yaml implements YAML 1.2.2 encoding and decoding.
The API follows the conventions of encoding/json: use Marshal and Unmarshal for one-shot conversions, Encoder and Decoder for streaming, and struct field tags to control mapping between YAML keys and Go fields.
For low-level AST access, Parse returns a File containing Node trees that can be inspected, mutated with Path queries, and re-serialized with NodeToBytes.
Struct Tags ¶
Struct fields may be annotated with "yaml" tags:
type Config struct {
Name string `yaml:"name"`
Count int `yaml:"count,omitempty"`
Ignored string `yaml:"-"`
}
The tag format is "keyname,opts" where opts is a comma-separated list of:
- omitempty: omit the field if it has its zero value
- inline: inline the struct's fields into the parent mapping
- flow: encode the field in flow style (e.g. [a, b] or {k: v})
- required: return an error during decoding if the key is absent
- default=<value>: set field to <value> during decoding if the key is absent (requires WithDefaults; scalar types only)
A tag of "-" excludes the field from encoding and decoding.
Custom Marshalers ¶
Types can implement Marshaler, BytesMarshaler, MarshalerContext, Unmarshaler, BytesUnmarshaler, or UnmarshalerContext for custom serialization logic.
Error Handling ¶
Decoding errors are returned as typed values that support errors.Is:
if errors.Is(err, yaml.ErrSyntax) { ... }
if errors.Is(err, yaml.ErrDuplicateKey) { ... }
Use FormatError to produce a human-readable error with a source pointer.
Index ¶
- Variables
- func FormatError(data []byte, err error, color ...bool) string
- func FromJSON(jsonData []byte) ([]byte, error)
- func Marshal(v any) ([]byte, error)
- func MarshalWithOptions(v any, opts ...EncodeOption) ([]byte, error)
- func NodeToBytes(n *Node) ([]byte, error)
- func NodeToBytesWithOptions(n *Node, opts ...EncodeOption) ([]byte, error)
- func ToJSON(yamlData []byte) ([]byte, error)
- func Unmarshal(data []byte, v any) error
- func UnmarshalTo[T any](data []byte, opts ...DecodeOption) (T, error)
- func UnmarshalWithOptions(data []byte, v any, opts ...DecodeOption) error
- func Valid(data []byte) bool
- func Walk(n *Node, fn WalkFunc)
- type BytesMarshaler
- type BytesUnmarshaler
- type Comment
- type CommentPosition
- type CycleError
- type DecodeOption
- func WithCustomUnmarshaler[T any](fn func(*T, []byte) error) DecodeOption
- func WithDefaults() DecodeOption
- func WithDisallowDuplicateKey() DecodeOption
- func WithJSONUnmarshaler() DecodeOption
- func WithMaxAliasExpansion(n int) DecodeOption
- func WithMaxDepth(n int) DecodeOption
- func WithMaxDocumentSize(n int) DecodeOption
- func WithMaxNodes(n int) DecodeOption
- func WithOrderedMap() DecodeOption
- func WithRecursiveDir(b bool) DecodeOption
- func WithReferenceDirs(dirs ...string) DecodeOption
- func WithReferenceFiles(files ...string) DecodeOption
- func WithSchema(s Schema) DecodeOption
- func WithStrict() DecodeOption
- func WithTagResolver(resolver *TagResolver) DecodeOption
- func WithValidator(v StructValidator) DecodeOption
- type Decoder
- type DefaultError
- type DuplicateKeyError
- type EncodeOption
- func WithAutoInt(b bool) EncodeOption
- func WithComment(comments map[string][]Comment) EncodeOption
- func WithCustomMarshaler[T any](fn func(T) ([]byte, error)) EncodeOption
- func WithFlow(b bool) EncodeOption
- func WithIndent(n int) EncodeOption
- func WithIndentSequence(b bool) EncodeOption
- func WithJSON(b bool) EncodeOption
- func WithLineWidth(n int) EncodeOption
- func WithLiteralStyle(b bool) EncodeOption
- func WithOmitEmpty(b bool) EncodeOption
- func WithQuoteAllStrings(b bool) EncodeOption
- func WithSingleQuote(b bool) EncodeOption
- type Encoder
- type File
- type MapItem
- type MapSlice
- type Marshaler
- type MarshalerContext
- type Node
- type NodeKind
- type Path
- func (p *Path) Append(n, value *Node) error
- func (p *Path) Delete(n *Node) error
- func (p *Path) Read(n *Node) ([]*Node, error)
- func (p *Path) ReadPositions(n *Node) ([]Position, error)
- func (p *Path) ReadString(data []byte) (string, error)
- func (p *Path) Replace(n, replacement *Node) error
- func (p *Path) String() string
- type Position
- type ScalarStyle
- type Schema
- type StructValidator
- type SyntaxError
- type TagResolver
- type TypeError
- type UnknownFieldError
- type Unmarshaler
- type UnmarshalerContext
- type ValidationError
- type WalkFunc
Examples ¶
- Filter
- FormatError
- FromJSON
- Marshal
- MarshalWithOptions
- NewDecoder
- NewEncoder
- Node.Validate
- NodeToBytes
- NodeToBytesWithOptions
- Parse
- Path.Append
- Path.Delete
- Path.Read
- Path.ReadPositions
- Path.ReadString
- Path.Replace
- PathString
- ToJSON
- Unmarshal
- UnmarshalTo
- UnmarshalWithOptions
- UnmarshalWithOptions (Strict)
- Valid
- Walk
- WithAutoInt
- WithComment
- WithCustomMarshaler
- WithCustomUnmarshaler
- WithDisallowDuplicateKey
- WithFlow
- WithIndent
- WithJSON
- WithLiteralStyle
- WithMaxAliasExpansion
- WithMaxDepth
- WithMaxDocumentSize
- WithOmitEmpty
- WithOrderedMap
- WithSchema
- WithSingleQuote
- WithStrict
- WithTagResolver
- WithValidator
Constants ¶
This section is empty.
Variables ¶
var ( ErrSyntax = &SyntaxError{} ErrType = &TypeError{} ErrUnknownField = &UnknownFieldError{} ErrCycle = &CycleError{} ErrDuplicateKey = &DuplicateKeyError{} ErrValidation = &ValidationError{} ErrDefault = &DefaultError{} ErrPathSyntax = errors.New("yaml: invalid path syntax") ErrPathNotFound = errors.New("yaml: path not found") ErrNilPointer = errors.New("yaml: non-nil pointer required") ErrDocumentSize = errors.New("yaml: document size exceeds limit") ErrPathEscape = errors.New("yaml: reference path escapes allowed directory") )
Sentinel errors for use with errors.Is.
Functions ¶
func FormatError ¶
FormatError returns a human-readable string for a SyntaxError or ValidationError that includes the offending source line and a column pointer. For other error types it returns err.Error(). Set color to true to include ANSI color escape sequences.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
data := []byte("key: [bad\n")
var v any
err := yaml.Unmarshal(data, &v)
if err != nil {
formatted := yaml.FormatError(data, err)
fmt.Print(formatted)
}
}
Output:
func FromJSON ¶
FromJSON converts JSON bytes to YAML bytes. The JSON input is decoded into an untyped value and then re-encoded as YAML.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
data, err := yaml.FromJSON([]byte(`{"name":"test","port":8080}`))
if err != nil {
panic(err)
}
fmt.Print(string(data))
}
Output: name: test port: 8080
func Marshal ¶
Marshal serializes v into YAML bytes using default encoding options.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
type Server struct {
Host string `yaml:"host"`
Port int `yaml:"port"`
}
v := Server{Host: "localhost", Port: 8080}
data, err := yaml.Marshal(v)
if err != nil {
panic(err)
}
fmt.Print(string(data))
}
Output: host: localhost port: 8080
func MarshalWithOptions ¶
func MarshalWithOptions(v any, opts ...EncodeOption) ([]byte, error)
MarshalWithOptions serializes v into YAML bytes, applying the given EncodeOption values to control formatting and style.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
v := map[string][]int{"nums": {1, 2, 3}}
data, err := yaml.MarshalWithOptions(v, yaml.WithFlow(true))
if err != nil {
panic(err)
}
fmt.Print(string(data))
}
Output: {nums: [1, 2, 3]}
func NodeToBytes ¶
NodeToBytes serializes a Node tree back into YAML bytes using default encoding options.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
file, _ := yaml.Parse([]byte("name: hello\n"))
out, err := yaml.NodeToBytes(file.Docs[0])
if err != nil {
panic(err)
}
fmt.Print(string(out))
}
Output: name: hello
func NodeToBytesWithOptions ¶
func NodeToBytesWithOptions(n *Node, opts ...EncodeOption) ([]byte, error)
NodeToBytesWithOptions serializes a Node tree back into YAML bytes using the provided encoding options.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
doc := &yaml.Node{
Kind: yaml.DocumentNode,
Children: []*yaml.Node{{
Kind: yaml.MappingNode,
Children: []*yaml.Node{
{Kind: yaml.ScalarNode, Value: "name"},
{Kind: yaml.ScalarNode, Value: "hello"},
},
}},
}
out, err := yaml.NodeToBytesWithOptions(doc, yaml.WithSingleQuote(true))
if err != nil {
panic(err)
}
fmt.Print(string(out))
}
Output: name: hello
func ToJSON ¶
ToJSON converts YAML bytes to JSON bytes. The YAML input is decoded into an untyped value and then re-encoded as JSON.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
data, err := yaml.ToJSON([]byte("name: test\ncount: 42\n"))
if err != nil {
panic(err)
}
fmt.Println(string(data))
}
Output: {"count":42,"name":"test"}
func Unmarshal ¶
Unmarshal parses YAML data and stores the first document into the value pointed to by v. If v is nil or not a pointer, Unmarshal returns an error.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
data := []byte("name: app\nport: 3000\n")
var v map[string]any
if err := yaml.Unmarshal(data, &v); err != nil {
panic(err)
}
fmt.Println(v["name"])
fmt.Println(v["port"])
}
Output: app 3000
func UnmarshalTo ¶
func UnmarshalTo[T any](data []byte, opts ...DecodeOption) (T, error)
UnmarshalTo parses YAML data into a value of type T and returns it. This is a generic alternative to Unmarshal that allocates the target value internally, removing the need for the caller to declare a variable and pass its address.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
type Config struct {
Name string `yaml:"name"`
Port int `yaml:"port"`
}
cfg, err := yaml.UnmarshalTo[Config]([]byte("name: api\nport: 9090\n"))
if err != nil {
panic(err)
}
fmt.Println(cfg.Name, cfg.Port)
}
Output: api 9090
func UnmarshalWithOptions ¶
func UnmarshalWithOptions(data []byte, v any, opts ...DecodeOption) error
UnmarshalWithOptions parses YAML data into v, applying the given DecodeOption values to control strictness, limits, and custom resolvers.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
data := []byte("name: test\n")
var v map[string]any
if err := yaml.UnmarshalWithOptions(data, &v, yaml.WithSchema(yaml.FailsafeSchema)); err != nil {
panic(err)
}
fmt.Println(v["name"])
}
Output: test
Example (Strict) ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
type Config struct {
Name string `yaml:"name"`
}
data := []byte("name: test\nunknown: field\n")
var cfg Config
err := yaml.UnmarshalWithOptions(data, &cfg, yaml.WithStrict())
fmt.Println(err != nil)
}
Output: true
func Valid ¶
Valid reports whether data is valid YAML.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
fmt.Println(yaml.Valid([]byte("key: value")))
fmt.Println(yaml.Valid([]byte("key: [invalid")))
}
Output: true false
func Walk ¶
Walk traverses the AST rooted at n in depth-first pre-order, calling fn for each node. If fn returns false, the node's children are not visited.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
file, _ := yaml.Parse([]byte("a: 1\nb: 2\n"))
var keys []string
yaml.Walk(file.Docs[0], func(n *yaml.Node) bool {
if n.Kind == yaml.MappingNode {
for i := 0; i < len(n.Children)-1; i += 2 {
keys = append(keys, n.Children[i].Value)
}
}
return true
})
fmt.Println(keys)
}
Output: [a b]
Types ¶
type BytesMarshaler ¶
BytesMarshaler is implemented by types that can encode themselves directly into YAML bytes.
type BytesUnmarshaler ¶
BytesUnmarshaler is implemented by types that can decode themselves from raw YAML bytes.
type Comment ¶
type Comment struct {
Position CommentPosition
Text string
}
Comment attaches a comment to a YAML node identified by key path when encoding with WithComment.
type CommentPosition ¶
type CommentPosition int
CommentPosition specifies where a Comment appears relative to its node.
const ( HeadCommentPos CommentPosition = iota // before the node LineCommentPos // on the same line, after the value FootCommentPos // after the node )
type CycleError ¶
CycleError is returned when alias expansion detects a cycle or exceeds the maximum expansion depth set by WithMaxAliasExpansion.
func (*CycleError) Error ¶
func (e *CycleError) Error() string
func (*CycleError) Is ¶
func (e *CycleError) Is(target error) bool
type DecodeOption ¶
type DecodeOption func(*decoderOptions)
DecodeOption configures the behavior of Unmarshal, UnmarshalWithOptions, and Decoder.
func WithCustomUnmarshaler ¶
func WithCustomUnmarshaler[T any](fn func(*T, []byte) error) DecodeOption
WithCustomUnmarshaler registers a function that decodes YAML bytes into a value of type T, overriding the default decoding for that type.
Example ¶
package main
import (
"fmt"
"strings"
"github.com/go-rotini/yaml"
)
func main() {
type IP [4]byte
var v struct {
Addr IP `yaml:"addr"`
}
err := yaml.UnmarshalWithOptions([]byte("addr: 10.0.0.1\n"), &v,
yaml.WithCustomUnmarshaler(func(ip *IP, data []byte) error {
s := strings.TrimSpace(string(data))
var a, b, c, d byte
fmt.Sscanf(s, "%d.%d.%d.%d", &a, &b, &c, &d)
*ip = IP{a, b, c, d}
return nil
}),
)
if err != nil {
panic(err)
}
fmt.Println(v.Addr)
}
Output: [10 0 0 1]
func WithDefaults ¶ added in v1.0.5
func WithDefaults() DecodeOption
WithDefaults enables applying default values from struct tags when a YAML key is absent from the input. Default values are specified with the "default=<value>" tag option (e.g. `yaml:"port,default=8080"`). Only scalar types are supported: string, bool, int/uint variants, float variants, and time.Duration. Without this option, default tags are ignored.
func WithDisallowDuplicateKey ¶
func WithDisallowDuplicateKey() DecodeOption
WithDisallowDuplicateKey causes decoding to return a DuplicateKeyError if a mapping contains the same key more than once.
Example ¶
package main
import (
"errors"
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
var v map[string]int
err := yaml.UnmarshalWithOptions([]byte("a: 1\na: 2\n"), &v, yaml.WithDisallowDuplicateKey())
fmt.Println(errors.Is(err, yaml.ErrDuplicateKey))
}
Output: true
func WithJSONUnmarshaler ¶
func WithJSONUnmarshaler() DecodeOption
WithJSONUnmarshaler causes the decoder to try a type's UnmarshalJSON method if no YAML-specific unmarshaler is found.
func WithMaxAliasExpansion ¶
func WithMaxAliasExpansion(n int) DecodeOption
WithMaxAliasExpansion limits the total number of alias expansions during decoding (default 1000). This prevents denial-of-service via exponentially expanding aliases (the "billion laughs" attack).
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
data := []byte("a: &x [1,2]\nb: &y [*x,*x]\nc: &z [*y,*y]\nd: [*z,*z]\n")
var v any
err := yaml.UnmarshalWithOptions(data, &v, yaml.WithMaxAliasExpansion(1))
fmt.Println(err != nil)
}
Output: true
func WithMaxDepth ¶
func WithMaxDepth(n int) DecodeOption
WithMaxDepth limits the nesting depth of the decoded value (default 100). Deeply nested documents are rejected with a SyntaxError.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
type Inner struct {
Value int `yaml:"value"`
}
type Outer struct {
Inner Inner `yaml:"inner"`
}
var v Outer
err := yaml.UnmarshalWithOptions([]byte("inner:\n value: 1\n"), &v, yaml.WithMaxDepth(100))
if err != nil {
panic(err)
}
fmt.Println(v.Inner.Value)
}
Output: 1
func WithMaxDocumentSize ¶
func WithMaxDocumentSize(n int) DecodeOption
WithMaxDocumentSize rejects input that exceeds n bytes before parsing begins.
Example ¶
package main
import (
"bytes"
"errors"
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
big := bytes.Repeat([]byte("a"), 1000)
var v any
err := yaml.UnmarshalWithOptions(big, &v, yaml.WithMaxDocumentSize(100))
fmt.Println(errors.Is(err, yaml.ErrDocumentSize))
}
Output: true
func WithMaxNodes ¶
func WithMaxNodes(n int) DecodeOption
WithMaxNodes limits the total number of AST nodes the parser may create. Zero means no limit.
func WithOrderedMap ¶
func WithOrderedMap() DecodeOption
WithOrderedMap causes decoding into any (interface{}) to produce MapSlice values for mappings instead of map[string]any, preserving key order.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
var v any
if err := yaml.UnmarshalWithOptions([]byte("b: 2\na: 1\n"), &v, yaml.WithOrderedMap()); err != nil {
panic(err)
}
ms := v.(yaml.MapSlice)
for _, item := range ms {
fmt.Printf("%s=%v\n", item.Key, item.Value)
}
}
Output: b=2 a=1
func WithRecursiveDir ¶
func WithRecursiveDir(b bool) DecodeOption
WithRecursiveDir controls whether WithReferenceDirs walks subdirectories recursively. Symlinks that escape the directory root are rejected.
func WithReferenceDirs ¶
func WithReferenceDirs(dirs ...string) DecodeOption
WithReferenceDirs loads all .yaml and .yml files in the given directories and makes their anchors available for alias resolution. By default only the top level of each directory is scanned; use WithRecursiveDir to walk subdirectories.
func WithReferenceFiles ¶
func WithReferenceFiles(files ...string) DecodeOption
WithReferenceFiles loads the given YAML files and makes their anchors available for alias resolution in the primary document.
func WithSchema ¶
func WithSchema(s Schema) DecodeOption
WithSchema selects the YAML tag resolution schema. The default is CoreSchema. Use JSONSchema for JSON-compatible resolution or FailsafeSchema to treat all plain scalars as strings.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
var v any
if err := yaml.UnmarshalWithOptions([]byte("val: true\n"), &v, yaml.WithSchema(yaml.FailsafeSchema)); err != nil {
panic(err)
}
m := v.(map[string]any)
fmt.Printf("%T: %v\n", m["val"], m["val"])
}
Output: string: true
func WithStrict ¶
func WithStrict() DecodeOption
WithStrict causes decoding to return an UnknownFieldError if a YAML key does not correspond to any field in the target struct.
Example ¶
package main
import (
"errors"
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
type Config struct {
Name string `yaml:"name"`
}
var cfg Config
err := yaml.UnmarshalWithOptions([]byte("name: ok\nextra: bad\n"), &cfg, yaml.WithStrict())
fmt.Println(errors.Is(err, yaml.ErrUnknownField))
}
Output: true
func WithTagResolver ¶
func WithTagResolver(resolver *TagResolver) DecodeOption
WithTagResolver registers a TagResolver that handles a custom YAML tag (e.g. "!mytype") during decoding.
Example ¶
package main
import (
"fmt"
"reflect"
"strings"
"github.com/go-rotini/yaml"
)
func main() {
resolver := &yaml.TagResolver{
Tag: "!upper",
GoType: reflect.TypeOf(""),
Resolve: func(value string) (any, error) {
return strings.ToUpper(value), nil
},
}
var v map[string]string
err := yaml.UnmarshalWithOptions([]byte("name: !upper hello\n"), &v, yaml.WithTagResolver(resolver))
if err != nil {
panic(err)
}
fmt.Println(v["name"])
}
Output: HELLO
func WithValidator ¶
func WithValidator(v StructValidator) DecodeOption
WithValidator registers a StructValidator that is called after each struct is fully decoded.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
type Config struct {
Port int `yaml:"port"`
}
validator := validatorFunc(func(v any) error {
if c, ok := v.(*Config); ok && c.Port < 1 {
return fmt.Errorf("port must be positive")
}
return nil
})
var cfg Config
err := yaml.UnmarshalWithOptions([]byte("port: 0\n"), &cfg, yaml.WithValidator(validator))
fmt.Println(err != nil)
}
type validatorFunc func(any) error
func (f validatorFunc) Struct(v any) error { return f(v) }
Output: true
type Decoder ¶
type Decoder struct {
// contains filtered or unexported fields
}
Decoder reads and decodes YAML documents from an input stream. Use successive calls to Decoder.Decode to iterate over a multi-document stream; it returns io.EOF when no more documents remain.
The entire input is consumed from the reader on the first call to Decode. For streams where documents arrive incrementally (e.g. from a network connection), callers should frame each document and decode individually with Unmarshal.
A Decoder is not safe for concurrent use. Callers that need to decode from multiple goroutines must provide their own synchronization.
func NewDecoder ¶
func NewDecoder(r io.Reader, opts ...DecodeOption) *Decoder
NewDecoder returns a new Decoder that reads from r.
Example ¶
package main
import (
"bytes"
"fmt"
"io"
"github.com/go-rotini/yaml"
)
func main() {
data := "---\nhello: world\n---\nfoo: bar\n"
dec := yaml.NewDecoder(bytes.NewReader([]byte(data)))
for {
var v map[string]string
err := dec.Decode(&v)
if err == io.EOF {
break
}
if err != nil {
panic(err)
}
fmt.Println(v)
}
}
Output: map[hello:world] map[foo:bar]
func (*Decoder) Decode ¶
Decode reads the next YAML document from the stream and stores it in the value pointed to by v. It returns io.EOF when the stream is exhausted.
func (*Decoder) DecodeContext ¶
DecodeContext reads the next YAML document, passing ctx to types that implement UnmarshalerContext.
type DefaultError ¶ added in v1.0.5
DefaultError is returned when a default value from a struct tag cannot be applied — for example, when the default string cannot be parsed into the target type, or when default is combined with required.
func (*DefaultError) Error ¶ added in v1.0.5
func (e *DefaultError) Error() string
func (*DefaultError) Is ¶ added in v1.0.5
func (e *DefaultError) Is(target error) bool
type DuplicateKeyError ¶
DuplicateKeyError is returned when decoding with WithDisallowDuplicateKey and a mapping contains the same key more than once.
func (*DuplicateKeyError) Error ¶
func (e *DuplicateKeyError) Error() string
func (*DuplicateKeyError) Is ¶
func (e *DuplicateKeyError) Is(target error) bool
type EncodeOption ¶
type EncodeOption func(*encoderOptions)
EncodeOption configures the behavior of Marshal, MarshalWithOptions, and Encoder.
func WithAutoInt ¶
func WithAutoInt(b bool) EncodeOption
WithAutoInt encodes float64 values that have no fractional part as integers (e.g. 42 instead of 42.0).
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
v := map[string]float64{"count": 42.0}
data, _ := yaml.MarshalWithOptions(v, yaml.WithAutoInt(true))
fmt.Print(string(data))
}
Output: count: 42
func WithComment ¶
func WithComment(comments map[string][]Comment) EncodeOption
WithComment attaches comments to nodes by dot-path key (e.g. "server.port"). Each key maps to a slice of Comment values specifying position and text.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
v := map[string]int{"port": 8080}
comments := map[string][]yaml.Comment{
"port": {{Position: yaml.LineCommentPos, Text: "server port"}},
}
data, _ := yaml.MarshalWithOptions(v, yaml.WithComment(comments))
fmt.Print(string(data))
}
Output: port: 8080 # server port
func WithCustomMarshaler ¶
func WithCustomMarshaler[T any](fn func(T) ([]byte, error)) EncodeOption
WithCustomMarshaler registers a function that encodes values of type T to YAML bytes, overriding the default encoding for that type.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
type Hex int
data, _ := yaml.MarshalWithOptions(
map[string]Hex{"code": 255},
yaml.WithCustomMarshaler(func(h Hex) ([]byte, error) {
return fmt.Appendf(nil, "0x%X", int(h)), nil
}),
)
fmt.Print(string(data))
}
Output: code: 0xFF
func WithFlow ¶
func WithFlow(b bool) EncodeOption
WithFlow encodes all values in flow style (JSON-like inline notation) when set to true.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
v := map[string][]string{"tags": {"go", "yaml"}}
data, _ := yaml.MarshalWithOptions(v, yaml.WithFlow(true))
fmt.Print(string(data))
}
Output: {tags: [go, yaml]}
func WithIndent ¶
func WithIndent(n int) EncodeOption
WithIndent sets the number of spaces per indentation level (default 2).
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
v := []string{"a", "b", "c"}
data, _ := yaml.MarshalWithOptions(v, yaml.WithIndent(4))
fmt.Print(string(data))
}
Output: - a - b - c
func WithIndentSequence ¶
func WithIndentSequence(b bool) EncodeOption
WithIndentSequence controls whether sequence items are indented relative to their parent key. When false (the default), the "- " prefix aligns with the parent's indentation level.
func WithJSON ¶
func WithJSON(b bool) EncodeOption
WithJSON enables JSON-compatible output: all strings are double-quoted, keys are quoted, and null is used instead of YAML's tilde notation.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
v := map[string]any{"name": "test", "active": true}
data, _ := yaml.MarshalWithOptions(v, yaml.WithJSON(true))
fmt.Print(string(data))
}
Output: "active": true "name": "test"
func WithLineWidth ¶
func WithLineWidth(n int) EncodeOption
WithLineWidth sets the preferred line width for scalar wrapping (default 80). The encoder may exceed this width when a single word is longer than the limit.
func WithLiteralStyle ¶
func WithLiteralStyle(b bool) EncodeOption
WithLiteralStyle encodes multi-line strings as YAML literal block scalars (|) instead of quoted scalars when set to true.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
type Msg struct {
Text string `yaml:"text"`
}
v := Msg{Text: "line1\nline2\n"}
data, _ := yaml.MarshalWithOptions(v, yaml.WithLiteralStyle(true))
fmt.Print(string(data))
}
Output: text: | line1 line2
func WithOmitEmpty ¶
func WithOmitEmpty(b bool) EncodeOption
WithOmitEmpty omits struct fields and map entries whose values are zero/empty, equivalent to adding ",omitempty" to every field tag.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
type Config struct {
Name string `yaml:"name"`
Tags []string `yaml:"tags,omitempty"`
Debug bool `yaml:"debug,omitempty"`
}
data, _ := yaml.MarshalWithOptions(Config{Name: "app"}, yaml.WithOmitEmpty(true))
fmt.Print(string(data))
}
Output: name: app
func WithQuoteAllStrings ¶
func WithQuoteAllStrings(b bool) EncodeOption
WithQuoteAllStrings forces all string scalar values to be quoted when set to true. Mapping keys remain unquoted unless they require quoting for syntactic reasons.
func WithSingleQuote ¶
func WithSingleQuote(b bool) EncodeOption
WithSingleQuote prefers single-quoted scalars over double-quoted when the value contains no characters requiring escape sequences.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
v := map[string]string{"name": "true"}
data, _ := yaml.MarshalWithOptions(v, yaml.WithSingleQuote(true))
fmt.Print(string(data))
}
Output: name: 'true'
type Encoder ¶
type Encoder struct {
// contains filtered or unexported fields
}
Encoder writes YAML values to an output stream. When multiple values are encoded, each is separated by a "---" document marker.
An Encoder is not safe for concurrent use. Callers that need to encode from multiple goroutines must provide their own synchronization.
func NewEncoder ¶
func NewEncoder(w io.Writer, opts ...EncodeOption) *Encoder
NewEncoder returns a new Encoder that writes to w.
Example ¶
package main
import (
"bytes"
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
var buf bytes.Buffer
enc := yaml.NewEncoder(&buf)
if err := enc.Encode(map[string]string{"a": "1"}); err != nil {
panic(err)
}
if err := enc.Encode(map[string]string{"b": "2"}); err != nil {
panic(err)
}
if err := enc.Close(); err != nil {
panic(err)
}
fmt.Print(buf.String())
}
Output: a: "1" --- b: "2"
func (*Encoder) Close ¶
Close is a no-op. It is provided for symmetry with NewEncoder so callers can use a defer pattern without harm.
func (*Encoder) EncodeContext ¶
EncodeContext writes the YAML encoding of v to the stream. The context is passed to types implementing MarshalerContext.
type File ¶
File is the result of parsing a YAML byte stream. It contains one Node per document in the stream.
func Parse ¶
Parse tokenizes and parses data into an AST. The returned File provides direct access to the document tree without decoding into Go values.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
data := []byte("name: hello\nitems:\n - a\n - b\n")
file, err := yaml.Parse(data)
if err != nil {
panic(err)
}
for _, doc := range file.Docs {
yaml.Walk(doc, func(n *yaml.Node) bool {
if n.Kind == yaml.ScalarNode {
fmt.Println(n.Value)
}
return true
})
}
}
Output: name hello items a b
type MapSlice ¶
type MapSlice []MapItem
MapSlice is an ordered slice of key-value pairs. It is used as the decoded representation of YAML mappings when WithOrderedMap is enabled, preserving the original key order that a plain map[string]any would lose.
type Marshaler ¶
Marshaler is implemented by types that can encode themselves into a YAML- compatible Go value. The returned value is then encoded normally.
type MarshalerContext ¶
MarshalerContext is like Marshaler but accepts a context, which is set via Encoder.EncodeContext.
type Node ¶
type Node struct {
Kind NodeKind
Tag string
Anchor string
Alias string
Value string
Style ScalarStyle
Flow bool // flow style ({} or []) for mappings and sequences
ExplicitStart bool // explicit document start marker (---)
ExplicitEnd bool // explicit document end marker (...)
MergeKey bool // node represents a merge key (<<)
Children []*Node
Pos Position
Comment string
HeadComment string
FootComment string
}
Node is a YAML AST node. For mappings, Children alternates key-value pairs (children[0] is the first key, children[1] its value, etc.). For sequences, each child is a list element. For documents, Children holds the root node.
func Filter ¶
Filter walks the AST rooted at n and returns all nodes for which fn returns true.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
file, _ := yaml.Parse([]byte("a: 1\nb: hello\nc: 3\n"))
scalars := yaml.Filter(file.Docs[0], func(n *yaml.Node) bool {
return n.Kind == yaml.ScalarNode
})
for _, s := range scalars {
fmt.Println(s.Value)
}
}
Output: a 1 b hello c 3
func (*Node) String ¶
String returns a short human-readable description of the node: the scalar value for scalars, a summary like "{mapping: 3 pairs}" for collections.
func (*Node) Validate ¶
Validate checks the structural consistency of the node tree rooted at n. It returns an error if a mapping has an odd number of children (missing value), or if an alias node references an empty name.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
file, _ := yaml.Parse([]byte("a: 1\nb: 2\n"))
err := file.Docs[0].Validate()
fmt.Println(err)
}
Output: <nil>
type Path ¶
type Path struct {
// contains filtered or unexported fields
}
Path is a compiled JSONPath-like expression for querying and mutating a YAML Node tree. Create one with PathString.
func PathString ¶
PathString compiles a JSONPath-like expression into a Path.
Supported syntax:
- $ — root node
- .key — child mapping key
- [n] — sequence index (negative indexes count from the end)
- .* or [*] — wildcard (all children)
- .. — recursive descent
Example: "$.servers[0].host" selects the host field of the first server.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
path, err := yaml.PathString("$.name")
if err != nil {
panic(err)
}
data := []byte("name: world\nport: 80\n")
result, err := path.ReadString(data)
if err != nil {
panic(err)
}
fmt.Println(result)
}
Output: world
func (*Path) Append ¶
Append adds value as a new child to each SequenceNode matched by the path within the tree rooted at n. Non-sequence matches are ignored.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
file, _ := yaml.Parse([]byte("items:\n- a\n- b\n"))
path, _ := yaml.PathString("$.items")
newItem := &yaml.Node{Kind: yaml.ScalarNode, Value: "c"}
if err := path.Append(file.Docs[0], newItem); err != nil {
panic(err)
}
nodes, _ := path.Read(file.Docs[0])
for _, child := range nodes[0].Children {
fmt.Println(child.Value)
}
}
Output: a b c
func (*Path) Delete ¶
Delete removes all nodes matching the path from the tree rooted at n. For mappings, both the key and value are removed. The path must have at least two segments (root + child).
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
file, _ := yaml.Parse([]byte("a: x\nb: y\nc: z\n"))
path, _ := yaml.PathString("$.b")
if err := path.Delete(file.Docs[0]); err != nil {
panic(err)
}
out, _ := yaml.NodeToBytes(file.Docs[0])
fmt.Print(string(out))
}
Output: a: x c: z
func (*Path) Read ¶
Read evaluates the path against the Node tree rooted at n and returns all matching nodes.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
file, _ := yaml.Parse([]byte("servers:\n - host: a\n - host: b\n"))
path, _ := yaml.PathString("$.servers[*].host")
nodes, err := path.Read(file.Docs[0])
if err != nil {
panic(err)
}
for _, n := range nodes {
fmt.Println(n.Value)
}
}
Output: a b
func (*Path) ReadPositions ¶
ReadPositions evaluates the path against the Node tree and returns the Position of every matching node.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
file, _ := yaml.Parse([]byte("a: 1\nb: 2\nc: 3\n"))
path, _ := yaml.PathString("$.b")
positions, err := path.ReadPositions(file.Docs[0])
if err != nil {
panic(err)
}
for _, pos := range positions {
fmt.Println(pos.Line)
}
}
Output: 2
func (*Path) ReadString ¶
ReadString is a convenience that parses YAML data, evaluates the path against the first document, and returns the scalar Value of the first match.
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
path, _ := yaml.PathString("$.database.port")
result, err := path.ReadString([]byte("database:\n port: 5432\n"))
if err != nil {
panic(err)
}
fmt.Println(result)
}
Output: 5432
func (*Path) Replace ¶
Replace finds all nodes matching the path within the tree rooted at n and replaces each with replacement. The path must have at least two segments (root + child).
Example ¶
package main
import (
"fmt"
"github.com/go-rotini/yaml"
)
func main() {
file, _ := yaml.Parse([]byte("name: old\n"))
path, _ := yaml.PathString("$.name")
replacement := &yaml.Node{Kind: yaml.ScalarNode, Value: "new"}
if err := path.Replace(file.Docs[0], replacement); err != nil {
panic(err)
}
out, _ := yaml.NodeToBytes(file.Docs[0])
fmt.Print(string(out))
}
Output: name: new
type ScalarStyle ¶
type ScalarStyle int
ScalarStyle indicates how a scalar was (or should be) represented in YAML.
const ( PlainStyle ScalarStyle = iota // unquoted (foo) SingleQuotedStyle // single-quoted ('foo') DoubleQuotedStyle // double-quoted ("foo") LiteralStyle // literal block (|) FoldedStyle // folded block (>) )
type Schema ¶
type Schema int
Schema selects the YAML tag resolution schema used when decoding plain scalars into interface{}/any values.
const ( // CoreSchema resolves plain scalars using the YAML 1.2 Core schema: // null (~, null, Null, NULL, empty), bool (true/false in any case), // int (decimal, hex 0x, octal 0o), float (including .inf, .nan). CoreSchema Schema = iota // JSONSchema resolves plain scalars like JSON: null (lowercase only), // true/false (lowercase only), and JSON-format numbers. JSONSchema // FailsafeSchema treats all plain scalars as strings with no type // coercion. Only explicitly tagged values are resolved. FailsafeSchema )
type StructValidator ¶
StructValidator validates a struct after all fields have been decoded. Implement this interface to integrate with validation libraries.
type SyntaxError ¶
SyntaxError is returned when the YAML input is malformed. Use errors.Is(err, ErrSyntax) to test for syntax errors generically.
func (*SyntaxError) Error ¶
func (e *SyntaxError) Error() string
func (*SyntaxError) Is ¶
func (e *SyntaxError) Is(target error) bool
type TagResolver ¶
TagResolver maps a custom YAML tag to a Go type and provides a function that converts the scalar string value into the target type. Register resolvers with WithTagResolver.
type TypeError ¶
type TypeError struct {
Errors []string
}
TypeError is returned when one or more YAML values cannot be assigned to the target Go types. Errors contains a message for each failed conversion.
type UnknownFieldError ¶
UnknownFieldError is returned when decoding with WithStrict and a YAML key has no corresponding struct field.
func (*UnknownFieldError) Error ¶
func (e *UnknownFieldError) Error() string
func (*UnknownFieldError) Is ¶
func (e *UnknownFieldError) Is(target error) bool
type Unmarshaler ¶
Unmarshaler is implemented by types that can decode themselves from YAML. The unmarshal function may be called with a pointer to decode the underlying YAML value into any Go type.
type UnmarshalerContext ¶
type UnmarshalerContext interface {
UnmarshalYAML(ctx context.Context, unmarshal func(any) error) error
}
UnmarshalerContext is like Unmarshaler but accepts a context, which is set via Decoder.DecodeContext.
type ValidationError ¶
ValidationError wraps an error returned by a StructValidator with the Position of the YAML node that was decoded into the struct. This allows validation errors to be pretty-printed with FormatError just like syntax errors.
func (*ValidationError) Error ¶
func (e *ValidationError) Error() string
func (*ValidationError) Is ¶
func (e *ValidationError) Is(target error) bool
func (*ValidationError) Unwrap ¶
func (e *ValidationError) Unwrap() error