yptr

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Apr 11, 2023 License: MIT Imports: 6 Imported by: 0

README

Go Report Card

yaml-jsonpointer

Package yptr is a Go package with a JSONPointer implementation that can walk though a yaml.Node tree.

Documentation

Read full doc on the Go package documentation page.

Contributing

The yaml-jsonpointer project team welcomes contributions from the community. For more detailed information, refer to CONTRIBUTING.md.

License

yaml-jsonpointer is available under the MIT license.

Documentation

Overview

Package yptr is a JSONPointer implementation that can walk through a yaml.Node tree.

yaml.Nodes preserve comments and locations in the source and can be useful to implement editing in-place functionality that uses JSONPointer to locate the fields to be edited.

It also implements a simple extension to the JSONPointers standard that handles pointers into k8s manifests which usually contain arrays whose elements are objects with a field that uniquely specifies the array entry (e.g. "name").

For example, given a JSON/YAML input document:

{"a": [{"k":"x", "v": 42}, {"k":"y", "v": 77}]}

If "k" is a field that contains a key that uniquiely identifies an element in a given array, we can select the node with the scalar 42 by first selecting the array element for which "k" has the value of "x", and then by walking to the field "v":

/a/~{"k":"x"}/v

The "~" token accepts an argument which is interpreted as JSON value to be used as "query-by-example" filter against elements of an array. The array element is selected if the query-by-example object is a (recursive) subset of the element.

The ~{...} extension can potentially locate multiple matches. For example, "~{}" effectively acts as a wildcard. This library offers the following APIs:

  • `FindAll`: retrieve multiple matches
  • `FindAllStrict`: retrieve multiple matches, but error if any paths are not found while traversing
  • `Find`: fetch only one match, and error if multiple matches are found

JSONPointer is designed to locate exactly one node in the tree. This can be achieved only if the effective schema of the JSON/YAML document mandates that there is an identifying key in each array element you want to point to. Using the "Find" function effectively performs a dynamic check of that invariant.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrTooManyResults means a pointer matches too many results (usually more than one expected result).
	ErrTooManyResults = fmt.Errorf("too many results")
	// ErrNotFound a pointer failed to find a match.
	ErrNotFound = fmt.Errorf("not found")
)

Functions

func Find

func Find(root *yaml.Node, ptr string) (*yaml.Node, error)

Find is like FindAll but returns ErrTooManyResults if multiple matches are located.

Example
package main

import (
	"fmt"

	yptr "github.com/zachelrath/yaml-jsonpointer"
	yaml "gopkg.in/yaml.v3"
)

func main() {
	src := `
a:
  b:
    c: 42
d:
- e
- f
`
	var n yaml.Node
	yaml.Unmarshal([]byte(src), &n)

	r, _ := yptr.Find(&n, `/a/b/c`)
	fmt.Printf("Scalar %q at %d:%d\n", r.Value, r.Line, r.Column)

	r, _ = yptr.Find(&n, `/d/0`)
	fmt.Printf("Scalar %q at %d:%d\n", r.Value, r.Line, r.Column)
}
Output:

Scalar "42" at 4:8
Scalar "e" at 6:3
Example (Extension)
package main

import (
	"fmt"

	yptr "github.com/zachelrath/yaml-jsonpointer"
	yaml "gopkg.in/yaml.v3"
)

func main() {
	src := `kind: Deployment
apiVersion: apps/v1
metadata:
  name: foo
spec:
  template:
    spec:
      replicas: 1
      containers:
      - name: app
        image: nginx
      - name: sidecar
        image: mysidecar
`
	var n yaml.Node
	yaml.Unmarshal([]byte(src), &n)

	r, _ := yptr.Find(&n, `/spec/template/spec/containers/1/image`)
	fmt.Printf("Scalar %q at %d:%d\n", r.Value, r.Line, r.Column)

	r, _ = yptr.Find(&n, `/spec/template/spec/containers/~{"name":"app"}/image`)
	fmt.Printf("Scalar %q at %d:%d\n", r.Value, r.Line, r.Column)

}
Output:

Scalar "mysidecar" at 13:16
Scalar "nginx" at 11:16
Example (JsonPointerCompat)
package main

import (
	"fmt"

	yptr "github.com/zachelrath/yaml-jsonpointer"
	yaml "gopkg.in/yaml.v3"
)

func main() {
	// the array item match syntax doesn't accidentally match a field that just happens
	// to contain the same characters.
	src := `a:
  "{\"b\":\"c\"}": d
`
	var n yaml.Node
	yaml.Unmarshal([]byte(src), &n)

	r, _ := yptr.Find(&n, `/a/{"b":"c"}`)

	fmt.Printf("Scalar %q at %d:%d\n", r.Value, r.Line, r.Column)

}
Output:

Scalar "d" at 2:20

func FindAll

func FindAll(root *yaml.Node, ptr string) ([]*yaml.Node, error)

FindAll finds any locations in the json/yaml tree pointed by root that match the extended JSONPointer passed in ptr.

func FindAllStrict

func FindAllStrict(root *yaml.Node, ptr string) ([]*yaml.Node, error)

FindAllStrict finds all locations in the json/yaml tree pointed by root that match the extended JSONPointer passed in ptr. Any sequence or mapping nodes encountered as part of traversal must match the expected path, otherwise ErrNotFound will be returned with no results.

Types

This section is empty.

Jump to

Keyboard shortcuts

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