jsonpath

package module
v0.0.0-...-1de76d7 Latest Latest
Warning

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

Go to latest
Published: Apr 7, 2021 License: MIT Imports: 3 Imported by: 27

README

GoDoc Build Status

jsonpath

This package extends the json.Decoder to support navigating a stream of JSON tokens. You should be able to use this extended Decoder places where a json.Decoder would have been used.

This Decoder has the following enhancements...

  • The Scan method supports scanning a JSON stream while extracting particular values along the way using PathActions.
  • The SeekTo method supports seeking forward in a JSON token stream to a particular path.
  • The Path method returns the path of the most recently parsed token.
  • The Token method has been modified to distinguish between strings that are object keys and strings that are values. Object key strings are returned as the KeyString type rather than a native string.

Installation

go get -u github.com/exponent-io/jsonpath

Example Usage

SeekTo
import "github.com/exponent-io/jsonpath"

var j = []byte(`[
  {"Space": "YCbCr", "Point": {"Y": 255, "Cb": 0, "Cr": -10}},
  {"Space": "RGB",   "Point": {"R": 98, "G": 218, "B": 255}}
]`)

w := json.NewDecoder(bytes.NewReader(j))
var v interface{}

w.SeekTo(1, "Point", "G")
w.Decode(&v) // v is 218
Scan with PathActions
var j = []byte(`{"colors":[
  {"Space": "YCbCr", "Point": {"Y": 255, "Cb": 0, "Cr": -10, "A": 58}},
  {"Space": "RGB",   "Point": {"R": 98, "G": 218, "B": 255, "A": 231}}
]}`)

var actions PathActions

// Extract the value at Point.A
actions.Add(func(d *Decoder) error {
  var alpha int
  err := d.Decode(&alpha)
  fmt.Printf("Alpha: %v\n", alpha)
  return err
}, "Point", "A")

w := NewDecoder(bytes.NewReader(j))
w.SeekTo("colors", 0)

var ok = true
var err error
for ok {
  ok, err = w.Scan(&actions)
  if err != nil && err != io.EOF {
    panic(err)
  }
}

Documentation

Overview

Extends the Go runtime's json.Decoder enabling navigation of a stream of json tokens.

Index

Examples

Constants

View Source
const AnyIndex = -2

AnyIndex can be used in a pattern to match any array index.

Variables

This section is empty.

Functions

This section is empty.

Types

type DecodeAction

type DecodeAction func(d *Decoder) error

DecodeAction handlers are called by the Decoder when scanning objects. See PathActions.Add for more detail.

type Decoder

type Decoder struct {
	json.Decoder
	// contains filtered or unexported fields
}

Decoder extends the Go runtime's encoding/json.Decoder to support navigating in a stream of JSON tokens.

func NewDecoder

func NewDecoder(r io.Reader) *Decoder

NewDecoder creates a new instance of the extended JSON Decoder.

func (*Decoder) Decode

func (d *Decoder) Decode(v interface{}) error

Decode reads the next JSON-encoded value from its input and stores it in the value pointed to by v. This is equivalent to encoding/json.Decode().

func (*Decoder) Path

func (d *Decoder) Path() JsonPath

Path returns a slice of string and/or int values representing the path from the root of the JSON object to the position of the most-recently parsed token.

func (*Decoder) Scan

func (d *Decoder) Scan(ext *PathActions) (bool, error)

Scan moves forward over the JSON stream consuming all the tokens at the current level (current object, current array) invoking each matching PathAction along the way.

Scan returns true if there are more contiguous values to scan (for example in an array).

Example
var j = []byte(`{"colors":[
		{"Space": "YCbCr", "Point": {"Y": 255, "Cb": 0, "Cr": -10, "A": 58}},
		{"Space": "RGB",   "Point": {"R": 98, "G": 218, "B": 255, "A": 231}}
	]}`)

var actions PathActions

// Extract the value at Point.A
actions.Add(func(d *Decoder) error {
	var alpha int
	err := d.Decode(&alpha)
	fmt.Printf("Alpha: %v\n", alpha)
	return err
}, "Point", "A")

w := NewDecoder(bytes.NewReader(j))
w.SeekTo("colors", 0)

var ok = true
var err error
for ok {
	ok, err = w.Scan(&actions)
	if err != nil && err != io.EOF {
		panic(err)
	}
}
Output:

Alpha: 58
Alpha: 231
Example (AnyIndex)
var j = []byte(`{"colors":[
		{"Space": "YCbCr", "Point": {"Y": 255, "Cb": 0, "Cr": -10, "A": 58}},
		{"Space": "RGB",   "Point": {"R": 98, "G": 218, "B": 255, "A": 231}}
	]}`)

var actions PathActions

// Extract the value at Point.A
actions.Add(func(d *Decoder) error {
	var cr int
	err := d.Decode(&cr)
	fmt.Printf("Chrominance (Cr): %v\n", cr)
	return err
}, "colors", AnyIndex, "Point", "Cr")

actions.Add(func(d *Decoder) error {
	var r int
	err := d.Decode(&r)
	fmt.Printf("Red: %v\n", r)
	return err
}, "colors", AnyIndex, "Point", "R")

w := NewDecoder(bytes.NewReader(j))

var ok = true
var err error
for ok {
	ok, err = w.Scan(&actions)
	if err != nil && err != io.EOF {
		panic(err)
	}
}
Output:

Chrominance (Cr): -10
Red: 98

func (*Decoder) SeekTo

func (d *Decoder) SeekTo(path ...interface{}) (bool, error)

SeekTo causes the Decoder to move forward to a given path in the JSON structure.

The path argument must consist of strings or integers. Each string specifies an JSON object key, and each integer specifies an index into a JSON array.

Consider the JSON structure

{ "a": [0,"s",12e4,{"b":0,"v":35} ] }

SeekTo("a",3,"v") will move to the value referenced by the "a" key in the current object, followed by a move to the 4th value (index 3) in the array, followed by a move to the value at key "v". In this example, a subsequent call to the decoder's Decode() would unmarshal the value 35.

SeekTo returns a boolean value indicating whether a match was found.

Decoder is intended to be used with a stream of tokens. As a result it navigates forward only.

Example
var j = []byte(`[
		{"Space": "YCbCr", "Point": {"Y": 255, "Cb": 0, "Cr": -10}},
		{"Space": "RGB",   "Point": {"R": 98, "G": 218, "B": 255}}
	]`)

w := NewDecoder(bytes.NewReader(j))
var v interface{}

w.SeekTo(0, "Space")
w.Decode(&v)
fmt.Printf("%v => %v\n", w.Path(), v)

w.SeekTo(0, "Point", "Cr")
w.Decode(&v)
fmt.Printf("%v => %v\n", w.Path(), v)

w.SeekTo(1, "Point", "G")
w.Decode(&v)
fmt.Printf("%v => %v\n", w.Path(), v)

// seek to the end of the object
w.SeekTo()
fmt.Printf("%v\n", w.Path())
Output:

[0 Space] => YCbCr
[0 Point Cr] => -10
[1 Point G] => 218
[]

func (*Decoder) Token

func (d *Decoder) Token() (json.Token, error)

Token is equivalent to the Token() method on json.Decoder. The primary difference is that it distinguishes between strings that are keys and and strings that are values. String tokens that are object keys are returned as a KeyString rather than as a native string.

type JsonPath

type JsonPath []interface{}

JsonPath is a slice of strings and/or integers. Each string specifies an JSON object key, and each integer specifies an index into a JSON array.

func (*JsonPath) Equal

func (p *JsonPath) Equal(o JsonPath) bool

Equal tests for equality between two JsonPath types.

func (*JsonPath) HasPrefix

func (p *JsonPath) HasPrefix(o JsonPath) bool

type KeyString

type KeyString string

KeyString is returned from Decoder.Token to represent each key in a JSON object value.

type PathActions

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

PathActions represents a collection of DecodeAction functions that should be called at certain path positions when scanning the JSON stream. PathActions can be created once and used many times in one or more JSON streams.

func (*PathActions) Add

func (je *PathActions) Add(action DecodeAction, path ...interface{})

Add specifies an action to call on the Decoder when the specified path is encountered.

Jump to

Keyboard shortcuts

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