jsonpath

package
v0.0.11 Latest Latest
Warning

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

Go to latest
Published: Jul 14, 2020 License: Apache-2.0 Imports: 11 Imported by: 3

Documentation

Overview

Package jsonpath is a template engine using jsonpath syntax, which can be seen at http://goessner.net/articles/JsonPath/. In addition, it has {range} {end} function to iterate list and slice. This package is copied from repo kubernetes/client-go. See: https://kubernetes.io/docs/reference/kubectl/jsonpath/

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrSyntax is used to indicate a syntax error while evaluating the expression
	ErrSyntax = errors.New("invalid syntax")
)
View Source
var NodeTypeName = map[NodeType]string{
	NodeText:       "NodeText",
	NodeArray:      "NodeArray",
	NodeList:       "NodeList",
	NodeField:      "NodeField",
	NodeIdentifier: "NodeIdentifier",
	NodeFilter:     "NodeFilter",
	NodeInt:        "NodeInt",
	NodeFloat:      "NodeFloat",
	NodeWildcard:   "NodeWildcard",
	NodeRecursive:  "NodeRecursive",
	NodeUnion:      "NodeUnion",
	NodeBool:       "NodeBool",
}

NodeTypeName maps node type code to node type text representation

Functions

func UnquoteExtend

func UnquoteExtend(s string) (string, error)

UnquoteExtend is almost same as strconv.Unquote(), but it support parse single quotes as a string

Types

type ArrayNode

type ArrayNode struct {
	NodeType
	Params [3]ParamsEntry // start, end, step
}

ArrayNode holds start, end, step information for array index selection

func (*ArrayNode) String

func (a *ArrayNode) String() string

type BoolNode

type BoolNode struct {
	NodeType
	Value bool
}

BoolNode holds bool value

func (*BoolNode) String

func (b *BoolNode) String() string

type FieldNode

type FieldNode struct {
	NodeType
	Value string
}

FieldNode holds field of struct

func (*FieldNode) String

func (f *FieldNode) String() string

type FilterNode

type FilterNode struct {
	NodeType
	Left     *ListNode
	Right    *ListNode
	Operator string
}

FilterNode holds operand and operator information for filter

func (*FilterNode) String

func (f *FilterNode) String() string

type FloatNode

type FloatNode struct {
	NodeType
	Value float64
}

FloatNode holds float value

func (*FloatNode) String

func (i *FloatNode) String() string

type IdentifierNode

type IdentifierNode struct {
	NodeType
	Name string
}

IdentifierNode holds an identifier

func (*IdentifierNode) String

func (f *IdentifierNode) String() string

type IntNode

type IntNode struct {
	NodeType
	Value int
}

IntNode holds integer value

func (*IntNode) String

func (i *IntNode) String() string

type JSONPath

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

JSONPath represents the expression to evaluate

func New

func New(expression string) *JSONPath

New creates a new JSONPath with the given name.

func (*JSONPath) AllowMissingKeys

func (j *JSONPath) AllowMissingKeys(allow bool) *JSONPath

AllowMissingKeys allows a caller to specify whether they want an error if a field or map key cannot be located, or simply an empty result. The receiver is returned for chaining.

func (*JSONPath) EvalResults

func (j *JSONPath) EvalResults(results []reflect.Value) ([]interface{}, error)

EvalResults writes the results into a slice of interfaces

Example (Array_filter)
package main

import (
	"bytes"
	"fmt"
	"os"

	"github.com/VirtusLab/go-extended/pkg/json"
	"github.com/VirtusLab/go-extended/pkg/jsonpath"
)

func main() {
	bs := []byte(`[
	{"key":"a","value" : "I"},
	{"key":"b","value" : "II"},
	{"key":"c","value" : "III"}
]`)

	expression := `{$[?(@.key=="b")].value}`

	data, err := json.ToInterface(bytes.NewReader(bs))
	if err != nil {
		_, _ = fmt.Fprint(os.Stderr, err)
	}

	results, err := jsonpath.New(expression).ExecuteToInterface(data)
	if err != nil {
		_, _ = fmt.Fprint(os.Stderr, err)
	}
	fmt.Println(results)

}
Output:

II
Example (Goessner)
package main

import (
	"bytes"
	"fmt"
	"os"
	"strings"

	"github.com/VirtusLab/go-extended/pkg/json"
	"github.com/VirtusLab/go-extended/pkg/jsonpath"
)

func main() {
	js := `{ "store": {
    "book": [ 
      { "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95
      },
      { "category": "fiction",
        "author": "Evelyn Waugh",
        "title": "Sword of Honour",
        "price": 12.99
      },
      { "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": 8.99
      },
      { "category": "fiction",
        "author": "J. R. R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95
    }
  }
}`

	expressions := []string{
		`{$.store.book[*].author}`,
		`{$..author}`,
		`{$..book[2].title}`,
		`{$..book[-1:].title}`,
		`{$..book[0,1].title}`,
		`{$..book[:2].title}`,
		`{$..book[?(@.isbn)].title}`,
		`{$..book[?(@.price < 10.0)].title}`,
		`{$.store.bicycle.color}`,
		`{$..book[?(@.author=='J. R. R. Tolkien')].title}`,
	}

	data, err := json.ToInterface(strings.NewReader(js))
	if err != nil {
		_, _ = fmt.Fprint(os.Stderr, err)
	}

	for _, expression := range expressions {
		writer := new(bytes.Buffer)
		err := jsonpath.New(expression).AllowMissingKeys(true).Execute(writer, data)
		if err != nil {
			_, _ = fmt.Fprint(os.Stderr, err)
		}
		fmt.Println(writer.String())
	}

}
Output:

Nigel Rees Evelyn Waugh Herman Melville J. R. R. Tolkien
Nigel Rees Evelyn Waugh Herman Melville J. R. R. Tolkien
Moby Dick
The Lord of the Rings
Sayings of the Century Sword of Honour
Sayings of the Century Sword of Honour
Moby Dick The Lord of the Rings
Sayings of the Century Moby Dick
red
The Lord of the Rings
Example (Kubectl_docs)
package main

import (
	"fmt"
	"os"
	"strings"

	"github.com/VirtusLab/go-extended/pkg/json"
	"github.com/VirtusLab/go-extended/pkg/jsonpath"
)

func main() {
	js := `{
  "kind": "List",
  "items":[
    {
      "kind":"None",
      "metadata":{"name":"127.0.0.1"},
      "status":{
        "capacity":{"cpu":"4"},
        "addresses":[{"type": "LegacyHostIP", "address":"127.0.0.1"}]
      }
    },
    {
      "kind":"None",
      "metadata":{"name":"127.0.0.2"},
      "status":{
        "capacity":{"cpu":"8"},
        "addresses":[
          {"type": "LegacyHostIP", "address":"127.0.0.2"},
          {"type": "another", "address":"127.0.0.3"}
        ]
      }
    }
  ],
  "users":[
    {
      "name": "myself",
      "user": {}
    },
    {
      "name": "e2e",
      "user": {"username": "admin", "password": "secret"}
    }
  ]
}`

	expressions := []string{
		`{.kind}`,
		`{['kind']}`,
		`{.items[*].metadata.name}`,
		`{.users[0].name}`,
		`{.items[*]['metadata.name','status.capacity']}`,
		`{.users[?(@.name=="e2e")].user.password}`,
		`{range .items[*]}[{.metadata.name},{.status.capacity}]{end}`,
	}

	data, err := json.ToInterface(strings.NewReader(js))
	if err != nil {
		_, _ = fmt.Fprint(os.Stderr, err)
	}

	for _, expression := range expressions {
		results, err := jsonpath.New(expression).ExecuteToInterface(data)
		if err != nil {
			_, _ = fmt.Fprint(os.Stderr, err)
		}
		fmt.Println(results)
	}

}
Output:

List
List
[127.0.0.1 127.0.0.2]
myself
[127.0.0.1 127.0.0.2 map[cpu:4] map[cpu:8]]
secret
[[ 127.0.0.1 , map[cpu:4] ] [ 127.0.0.2 , map[cpu:8] ]]
Example (Simple)
package main

import (
	"fmt"
	"os"
	"strings"

	"github.com/VirtusLab/go-extended/pkg/json"
	"github.com/VirtusLab/go-extended/pkg/jsonpath"
)

func main() {
	js := `{
	"welcome":{
		"message":["Good Morning", "Hello World!"]
	}
}`
	expression := "{$.welcome.message[1]}"

	data, err := json.ToInterface(strings.NewReader(js))
	if err != nil {
		_, _ = fmt.Fprint(os.Stderr, err)
	}

	results, err := jsonpath.New(expression).ExecuteToInterface(data)
	if err != nil {
		_, _ = fmt.Fprint(os.Stderr, err)
	}
	fmt.Println(results)

}
Output:

Hello World!
Example (Yaml)
package main

import (
	"fmt"
	"os"
	"strings"

	"github.com/VirtusLab/go-extended/pkg/jsonpath"
	"github.com/VirtusLab/go-extended/pkg/yaml"
)

func main() {
	y := `---
welcome:
  message:
  - "Good Morning"
  - "Hello World!"
`
	expression := "{$.welcome.message[1]}"

	data, err := yaml.ToInterface(strings.NewReader(y))
	if err != nil {
		_, _ = fmt.Fprint(os.Stderr, err)
	}

	results, err := jsonpath.New(expression).ExecuteToInterface(data)
	if err != nil {
		_, _ = fmt.Fprint(os.Stderr, err)
	}
	fmt.Println(results)

}
Output:

Hello World!

func (*JSONPath) EvalToInterface

func (*JSONPath) EvalToInterface(v reflect.Value) (interface{}, error)

EvalToInterface translates reflect value to corresponding text

func (*JSONPath) EvalToText

func (j *JSONPath) EvalToText(v reflect.Value) ([]byte, error)

EvalToText translates reflect value to corresponding text

func (*JSONPath) Execute

func (j *JSONPath) Execute(wr io.Writer, data interface{}) error

Execute bounds data into template and writes the result.

func (*JSONPath) ExecuteToInterface

func (j *JSONPath) ExecuteToInterface(data interface{}) (interface{}, error)

ExecuteToInterface bounds data into template and returns the result.

func (*JSONPath) FindResults

func (j *JSONPath) FindResults(data interface{}) ([][]reflect.Value, error)

FindResults searches recursively the data evaluating the path expression

func (*JSONPath) Parse

func (j *JSONPath) Parse() error

Parse parses the given expression or returns an error

func (*JSONPath) PrintResults

func (j *JSONPath) PrintResults(wr io.Writer, results []reflect.Value) error

PrintResults writes the results into writer

type ListNode

type ListNode struct {
	NodeType
	Nodes []Node // The element nodes in lexical order.
}

ListNode holds a sequence of nodes.

func (*ListNode) String

func (l *ListNode) String() string

type Node

type Node interface {
	Type() NodeType
	String() string
}

Node represents a parse tree node

type NodeType

type NodeType int

NodeType identifies the type of a parse tree node.

const (
	// NodeText is a text node type code
	NodeText NodeType = iota
	// NodeArray is an array node type code
	NodeArray
	// NodeList is a list node type code
	NodeList
	// NodeField is a field node type code
	NodeField
	// NodeIdentifier is an identifier node type code
	NodeIdentifier
	// NodeFilter is a filter node type code
	NodeFilter
	// NodeInt is an integer node type code
	NodeInt
	// NodeFloat is a float node type code
	NodeFloat
	// NodeWildcard is a wildcard node type code
	NodeWildcard
	// NodeRecursive is a recursive node type code
	NodeRecursive
	// NodeUnion is a union node type code
	NodeUnion
	// NodeBool is a boolean node type code
	NodeBool
)

func (NodeType) String

func (t NodeType) String() string

func (NodeType) Type

func (t NodeType) Type() NodeType

Type returns itself and provides an easy default implementation

type ParamsEntry

type ParamsEntry struct {
	Value   int
	Known   bool // whether the value is known when parse it
	Derived bool
}

ParamsEntry holds param information for ArrayNode

type Parser

type Parser struct {
	Name string
	Root *ListNode
	// contains filtered or unexported fields
}

Parser represents the JSONPath flavour syntax parser

func NewParser

func NewParser(name string) *Parser

NewParser creates a new Parser

func Parse

func Parse(name, text string) (*Parser, error)

Parse parses the given text and return a node Parser. If an error is encountered, parsing stops and an empty Parser is returned with the error

func (*Parser) Parse

func (p *Parser) Parse(text string) error

Parse parses the given text

type RecursiveNode

type RecursiveNode struct {
	NodeType
}

RecursiveNode means a recursive descent operator

func (*RecursiveNode) String

func (r *RecursiveNode) String() string

type TextNode

type TextNode struct {
	NodeType
	Text string // The text; may span newlines.
}

TextNode holds plain text.

func (*TextNode) String

func (t *TextNode) String() string

type UnionNode

type UnionNode struct {
	NodeType
	Nodes []*ListNode
}

UnionNode is union of ListNode

func (*UnionNode) String

func (u *UnionNode) String() string

type WildcardNode

type WildcardNode struct {
	NodeType
}

WildcardNode means a wildcard

func (*WildcardNode) String

func (i *WildcardNode) String() string

Directories

Path Synopsis
Package template helps to implement jsonpath parser This package is copied from Go library text/template.
Package template helps to implement jsonpath parser This package is copied from Go library text/template.

Jump to

Keyboard shortcuts

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