---
title: "Read YAML without a struct"
url: https://recursiveai.org/oneyaml/go/cookbook/read-yaml-without-a-struct/
description: "Read values from YAML by JSON Pointer in Go, walk mappings and sequences with oneyaml’s Node, and get each value’s line, column and comment."
version: "1.0.0"
---

# Read YAML without a struct

When you don’t have a struct for the data, parse it into a `Document` and read values by JSON Pointer, or walk its nodes. A node also gives you its position and its comments.

```go
package main

import (
	"fmt"
	"log"

	oneyaml "oneyaml.dev/go"
)

func main() {
	doc, err := oneyaml.Parse([]byte(`server:
  host: 0.0.0.0
  port: 8080   # behind the load balancer
features: [auth, metrics]
limits:
  cpu: 0.5
  memory: 512Mi
`))
	if err != nil {
		log.Fatal(err)
	}

	// Read one value into a Go type, by JSON Pointer.
	var port int
	if err := doc.Get("/server/port", &port); err != nil {
		log.Fatal(err)
	}
	fmt.Println("port:", port)

	// Or walk the nodes: values, comments and positions.
	root := doc.Root()
	server, _ := root.Lookup("server")
	p, _ := server.Lookup("port")
	line, col := p.Position()
	fmt.Printf("port %s at %d:%d, comment %q\n", p.Value(), line, col, p.LineComment())

	features, _ := root.Lookup("features")
	for f := range features.Items() {
		fmt.Println("feature:", f.Value())
	}
	limits, _ := root.Lookup("limits")
	for k, v := range limits.Entries() {
		fmt.Printf("limit %s = %s\n", k.Value(), v.Value())
	}

	// A missing path is ErrNotFound, never a panic.
	var tls bool
	fmt.Println(doc.Get("/server/tls", &tls))
}
```

```text
port: 8080
port 8080 at 3:9, comment "# behind the load balancer"
feature: auth
feature: metrics
limit cpu = 0.5
limit memory = 512Mi
oneyaml: get "/server/tls": path not found
```

## Good to know

- `doc.Get(ptr, &v)` decodes the node at a JSON Pointer into any Go value, with the same rules as `Unmarshal`. A missing path returns an error that matches `oneyaml.ErrNotFound` with `errors.Is`.
- `Lookup` finds a key in a mapping; `Find` does the same but returns an error. `Entries()` and `Items()` are range-over-func iterators, in file order.
- `Position()` is the 1-based line and column, `Span()` the byte range, and `HeadComment()` and `LineComment()` the comments above and after the node.
- To read into plain Go values instead, `Unmarshal` into `any`: a mapping becomes `map[string]any`, a sequence `[]any`, an integer `int`.

A longer walk-through, with yaml.v2 and v3 compared: [Golang: read a YAML file without a struct](https://recursiveai.org/oneyaml/articles/golang-read-yaml-without-struct/).
