Package rfc6901

import "funnyhaha.technology/rfc/rfc6901"
View the source code

Overview

Package rfc6901 implements JSON Pointer, defined by RFC 6901 (JavaScript Object Notation (JSON) Pointer): a string such as "/profile/color" that identifies a value within a JSON document.

A Pointer is a sequence of reference tokens. Build one from tokens with New, which escapes them, or parse one from its string form with Parse or its URI fragment form with ParseFragment:

rfc6901.New("profile", "color").String()   // "/profile/color"
rfc6901.New("a/b").String()                // "/a~1b"
rfc6901.New("profile", "color").Fragment() // "#/profile/color"

The package doesn't evaluate a pointer against a document (Section 4).

The RFC text is in rfc6901.txt in this directory, and the doc comments cite its sections.

Index

Variables

var ErrInvalidPointer = errors.New("invalid JSON pointer")
source

ErrInvalidPointer is returned for a string that isn't a JSON Pointer.

Types

Pointer source

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

Pointer is a JSON Pointer: a sequence of reference tokens. The zero Pointer has no tokens and identifies the whole document.

Pointer is immutable: Append and AppendIndex return a new Pointer.

See RFC 6901, Section 3.

New source

func New(tokens ...string) Pointer

New returns a pointer with the given reference tokens, unescaped: New("a/b") identifies the member named "a/b".

Example

ExampleNew shows a pointer's string and fragment forms, and how "/" and "~" in a token are escaped.

package main

import (
	"fmt"

	"funnyhaha.technology/rfc/rfc6901"
)

func main() {
	p := rfc6901.New("profile", "color")

	fmt.Println(p)
	fmt.Println(p.Fragment())
	fmt.Println(rfc6901.New("a/b", "m~n"))
}

Output:

/profile/color
#/profile/color
/a~1b/m~0n

Parse source

func Parse(s string) (Pointer, error)

Parse parses the string form of a pointer, such as "/a~1b/0" (Section 5). It returns ErrInvalidPointer if s is neither empty nor starts with "/", has a "~" not followed by "0" or "1", or isn't valid UTF-8.

Example

ExampleParse shows an escaped pointer parsed back to its tokens.

package main

import (
	"fmt"

	"funnyhaha.technology/rfc/rfc6901"
)

func main() {
	p, err := rfc6901.Parse("/a~1b/0")
	if err != nil {
		panic(err)
	}
	fmt.Printf("%q\n", p.Tokens())
}

Output:

["a/b" "0"]

ParseFragment source

func ParseFragment(s string) (Pointer, error)

ParseFragment parses the URI fragment form of a pointer, such as "#/c%25d" (Section 6). It percent-decodes s after the "#", then parses it as Parse does.

(Pointer) Append source

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

Append returns a pointer with the tokens added to the end of p's.

(Pointer) AppendIndex source

func (p Pointer) AppendIndex(i int) Pointer

AppendIndex returns a pointer with an array index added to the end of p's. It panics if i is negative, as indexing a slice does.

(Pointer) Fragment source

func (p Pointer) Fragment() string

Fragment returns the URI fragment form of p, starting with "#", with the octets the fragment rule of RFC 3986 doesn't allow percent-encoded (Section 6).

(Pointer) MarshalText source

func (p Pointer) MarshalText() ([]byte, error)

MarshalText returns the string form of p, so a Pointer encodes as a JSON string.

(Pointer) String source

func (p Pointer) String() string

String returns the string form of p, escaping "~" as "~0" and "/" as "~1" in each token (Section 3).

(Pointer) Tokens source

func (p Pointer) Tokens() []string

Tokens returns a copy of p's reference tokens, unescaped.

(Pointer) UnmarshalText source

func (p *Pointer) UnmarshalText(text []byte) error

UnmarshalText parses the string form of a pointer into p.