jsonpointer

package module
v0.4.27 Latest Latest
Warning

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

Go to latest
Published: Jul 4, 2026 License: MIT Imports: 5 Imported by: 7

README

JSON Pointer

Go Module Go Reference

A read-only JSON Pointer (RFC 6901) library for Go built around one strict, immutable Pointer value.

Features

  • Strict RFC 6901 parsing: malformed pointer strings return errors instead of becoming lookup keys.
  • Raw token construction: build pointers from literal Go strings without confusing token text with pointer-string syntax.
  • Go-native traversal: read JSON-shaped maps, slices, arrays, typed string-keyed maps, pointers, and interface-wrapped values.
  • Explicit errors: keep errors.Is sentinel checks and use errors.As for pointer, token, and depth context.
  • Small API: parse or build a Pointer, then ask it for a value or reference.
  • Fast common paths: optimize decoded JSON shapes such as map[string]any and []any before typed-container fallbacks.

Installation

go get github.com/kaptinlin/jsonpointer

Requires the Go version declared in go.mod.

Quick Start

package main

import (
	"fmt"
	"log"

	"github.com/kaptinlin/jsonpointer"
)

func main() {
	doc := map[string]any{
		"users": []any{
			map[string]any{"name": "Alice"},
		},
	}

	p, err := jsonpointer.Parse("/users/0/name")
	if err != nil {
		log.Fatal(err)
	}

	name, err := p.Value(doc)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(name)
}

Core APIs

API Description
Parse(pointer string) (Pointer, error) Parse a strict JSON Pointer string
FromTokens(tokens ...string) Pointer Build a pointer from raw token strings
Root() Pointer Return the root pointer
(Pointer).String() string Format the canonical JSON Pointer string
(Pointer).Tokens() []string Return a copy of the raw tokens
(Pointer).Parent() (Pointer, error) Return the parent pointer
(Pointer).Child(tokens ...string) Pointer Return a child pointer
(Pointer).Value(doc any) (any, error) Resolve a value
(Pointer).Reference(doc any) (Reference, error) Resolve a value with parent context
Value(doc any, pointer string) (any, error) Strict one-shot value lookup
ReferenceOf(doc any, pointer string) (Reference, error) Strict one-shot reference lookup
EscapeToken(token string) string Escape one raw token
UnescapeToken(encoded string) (string, error) Decode one escaped token strictly
IsArrayIndex(token string) bool Report whether a token is a canonical, representable array index

Parse("/~2") returns ErrInvalidPointer. FromTokens("~2") succeeds because "~2" is literal token data, not pointer-string syntax.

Reference Results

Pointer.Reference and ReferenceOf return a Reference with named accessors:

Method Meaning
Value() any The resolved value
Parent() (any, bool) The parent container when one exists
Token() string The final token used to reach the value
Pointer() Pointer The pointer used for traversal

Root references have no parent and return (nil, false) from Parent. For non-root references, Parent is the dereferenced container that consumed the final token, so pointer and interface wrappers do not leak into reference context.

Examples

Build from raw tokens
p := jsonpointer.FromTokens("foo/bar", "tilde~key")
fmt.Println(p.String())

Output:

/foo~1bar/tilde~0key
Read with parent context
doc := map[string]any{
	"foo/bar": map[string]any{
		"tilde~key": "ready",
	},
}

p, err := jsonpointer.Parse("/foo~1bar/tilde~0key")
if err != nil {
	log.Fatal(err)
}

ref, err := p.Reference(doc)
if err != nil {
	log.Fatal(err)
}
fmt.Println(ref.Value())
fmt.Println(ref.Token())
Traverse typed containers
type Key string

doc := map[string]any{
	"labels": map[Key]string{
		"status": "ready",
	},
}

p := jsonpointer.FromTokens("labels", "status")
status, err := p.Value(doc)
if err != nil {
	log.Fatal(err)
}
fmt.Println(status)

Traversal follows JSON-shaped containers. Structs are not field-selected; convert struct values to a JSON document shape before using JSON Pointer over fields.

Error Handling

Pointer construction and navigation sentinel errors include:

  • ErrInvalidPointer
  • ErrNoParent

Traversal sentinel errors include:

  • ErrKeyNotFound
  • ErrInvalidIndex
  • ErrIndexOutOfBounds
  • ErrNilPointer
  • ErrNotFound

For arrays, malformed index tokens such as 01, +1, non-ASCII digits, or decimal text return ErrInvalidIndex. -, indexes outside the collection, and canonical decimal indexes too large to represent return ErrIndexOutOfBounds.

Use errors.Is for error classes and errors.As when traversal context matters:

value, err := jsonpointer.Value(doc, "/users/1/name")
if errors.Is(err, jsonpointer.ErrIndexOutOfBounds) {
	var pointerErr *jsonpointer.Error
	if errors.As(err, &pointerErr) {
		fmt.Println(pointerErr.Pointer(), pointerErr.Token(), pointerErr.Depth())
	}
}
_ = value

Performance

The package optimizes common map[string]any and []any reads and falls back to reflection only for typed container mechanics such as slices, arrays, maps, pointers, and interfaces. Reuse parsed pointers when resolving the same location repeatedly.

See benchmarks/README.md for benchmark coverage.

Run benchmarks with:

task bench

Development

task test          # Run package tests with the race detector
task lint          # Run golangci-lint and tidy checks
task specs-check   # Validate spec and design doc placement
task yamllint      # Lint YAML files
task bench         # Run benchmark suites

Run the demo program with:

go run ./examples

For development workflow and package contracts, see AGENTS.md and SPECS/.

Contributing

Contributions are welcome. Keep README.md, example_test.go, and the relevant SPECS/ documents aligned when public behavior changes.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Documentation

Overview

Package jsonpointer implements read-only JSON Pointer (RFC 6901) traversal for Go values.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidIndex is returned when an array token is not a canonical index.
	ErrInvalidIndex = errors.New("invalid array index")

	// ErrIndexOutOfBounds is returned when an array index is outside the array.
	ErrIndexOutOfBounds = errors.New("array index out of bounds")

	// ErrKeyNotFound is returned when a map key is missing.
	ErrKeyNotFound = errors.New("map key not found")

	// ErrNilPointer is returned when traversal must dereference a nil pointer.
	ErrNilPointer = errors.New("cannot traverse through nil pointer")

	// ErrNotFound is returned when a value cannot be traversed.
	ErrNotFound = errors.New("not found")

	// ErrNoParent is returned when asking for the parent of the root pointer.
	ErrNoParent = errors.New("no parent")
)
View Source
var (
	// ErrInvalidPointer is returned when a JSON Pointer string is invalid.
	ErrInvalidPointer = errors.New("invalid pointer")
)

Functions

func EscapeToken added in v0.4.27

func EscapeToken(token string) string

EscapeToken escapes a raw token for use inside a JSON Pointer string.

func IsArrayIndex added in v0.4.27

func IsArrayIndex(token string) bool

IsArrayIndex reports whether token is a canonical, representable array index.

func UnescapeToken added in v0.4.27

func UnescapeToken(encoded string) (string, error)

UnescapeToken decodes one JSON Pointer token.

func Value added in v0.4.27

func Value(doc any, pointer string) (any, error)

Value parses pointer and resolves it against doc.

Example
package main

import (
	"fmt"
	"log"

	"github.com/kaptinlin/jsonpointer"
)

func main() {
	doc := map[string]any{"name": "Alice"}

	name, err := jsonpointer.Value(doc, "/name")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(name)
}
Output:
Alice

Types

type Error added in v0.4.27

type Error struct {
	// contains filtered or unexported fields
}

Error wraps a traversal failure with machine-readable pointer context.

func (*Error) Depth added in v0.4.27

func (e *Error) Depth() int

Depth returns the zero-based token depth where the error occurred.

func (*Error) Error added in v0.4.27

func (e *Error) Error() string

Error returns a human-readable error message.

func (*Error) Pointer added in v0.4.27

func (e *Error) Pointer() Pointer

Pointer returns the requested pointer being resolved.

func (*Error) Token added in v0.4.27

func (e *Error) Token() string

Token returns the token being resolved when the error occurred.

func (*Error) Unwrap added in v0.4.27

func (e *Error) Unwrap() error

Unwrap returns the sentinel cause for errors.Is checks.

type Pointer added in v0.4.27

type Pointer struct {
	// contains filtered or unexported fields
}

Pointer is an immutable RFC 6901 JSON Pointer.

func FromTokens added in v0.4.27

func FromTokens(tokens ...string) Pointer

FromTokens builds a pointer from raw, unescaped token strings.

Example
package main

import (
	"fmt"

	"github.com/kaptinlin/jsonpointer"
)

func main() {
	p := jsonpointer.FromTokens("foo/bar", "tilde~key")

	fmt.Println(p.String())
	fmt.Println(p.Tokens())
}
Output:
/foo~1bar/tilde~0key
[foo/bar tilde~key]

func Parse added in v0.3.0

func Parse(pointer string) (Pointer, error)

Parse parses a strict RFC 6901 JSON Pointer string.

func Root added in v0.4.27

func Root() Pointer

Root returns the root pointer.

func (Pointer) Child added in v0.4.27

func (p Pointer) Child(tokens ...string) Pointer

Child returns a new pointer with tokens appended.

func (Pointer) IsRoot added in v0.4.27

func (p Pointer) IsRoot() bool

IsRoot reports whether p points at the root value.

func (Pointer) Parent added in v0.4.27

func (p Pointer) Parent() (Pointer, error)

Parent returns the parent pointer.

func (Pointer) Reference added in v0.4.27

func (p Pointer) Reference(doc any) (Reference, error)

Reference resolves p against doc and returns value plus parent context.

Example
package main

import (
	"fmt"
	"log"

	"github.com/kaptinlin/jsonpointer"
)

func main() {
	doc := map[string]any{
		"foo/bar": map[string]any{
			"tilde~key": "ready",
		},
	}

	p, err := jsonpointer.Parse("/foo~1bar/tilde~0key")
	if err != nil {
		log.Fatal(err)
	}
	ref, err := p.Reference(doc)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(ref.Value())
	fmt.Println(ref.Token())
}
Output:
ready
tilde~key

func (Pointer) String added in v0.4.27

func (p Pointer) String() string

String returns the canonical RFC 6901 string form.

func (Pointer) Tokens added in v0.4.27

func (p Pointer) Tokens() []string

Tokens returns a copy of the pointer tokens.

func (Pointer) Value added in v0.4.27

func (p Pointer) Value(doc any) (any, error)

Value resolves p against doc and returns the value.

Example
package main

import (
	"fmt"
	"log"

	"github.com/kaptinlin/jsonpointer"
)

func main() {
	doc := map[string]any{
		"users": []any{
			map[string]any{"name": "Alice"},
		},
	}

	p, err := jsonpointer.Parse("/users/0/name")
	if err != nil {
		log.Fatal(err)
	}
	name, err := p.Value(doc)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(name)
}
Output:
Alice

type Reference

type Reference struct {
	// contains filtered or unexported fields
}

Reference is a resolved value with its parent traversal context.

func ReferenceOf added in v0.4.27

func ReferenceOf(doc any, pointer string) (Reference, error)

ReferenceOf parses pointer and resolves it against doc with parent context.

func (Reference) Parent added in v0.4.27

func (r Reference) Parent() (any, bool)

Parent returns the parent container when the reference is not the root.

func (Reference) Pointer added in v0.4.27

func (r Reference) Pointer() Pointer

Pointer returns the pointer that produced the reference.

func (Reference) Token added in v0.4.27

func (r Reference) Token() string

Token returns the final pointer token used to reach the value.

func (Reference) Value added in v0.4.27

func (r Reference) Value() any

Value returns the resolved value.

Directories

Path Synopsis
Package main demonstrates the jsonpointer API.
Package main demonstrates the jsonpointer API.

Jump to

Keyboard shortcuts

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