Documentation
¶
Overview ¶
Package jsonpath implements RFC 9535 JSONPath query expressions.
Example ¶
Select all the authors of the books in a bookstore object.
package main import ( "encoding/json" "fmt" "log" "github.com/theory/jsonpath" ) func main() { // Parse a jsonpath query. p, err := jsonpath.Parse(`$.store.book[*].author`) if err != nil { log.Fatal(err) } // Select values from unmarshaled JSON input. store := bookstore() nodes := p.Select(store) // Show the selected values. items, err := json.Marshal(nodes) if err != nil { log.Fatal(err) } fmt.Printf("%s\n", items) } // bookstore returns an unmarshaled JSON object. func bookstore() any { src := []byte(`{ "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": 399 } } }`) var value any if err := json.Unmarshal(src, &value); err != nil { log.Fatal(err) } return value }
Output: ["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]
Index ¶
- Variables
- type LocatedNodeList
- func (list LocatedNodeList) All() iter.Seq[*spec.LocatedNode]
- func (list LocatedNodeList) Clone() LocatedNodeList
- func (list LocatedNodeList) Deduplicate() LocatedNodeList
- func (list LocatedNodeList) Nodes() iter.Seq[any]
- func (list LocatedNodeList) Paths() iter.Seq[spec.NormalizedPath]
- func (list LocatedNodeList) Sort()
- type NodeList
- type Option
- type Parser
- type Path
- func (p *Path) MarshalBinary() ([]byte, error)
- func (p *Path) MarshalText() ([]byte, error)
- func (p *Path) Query() *spec.PathQuery
- func (p *Path) Select(input any) NodeList
- func (p *Path) SelectLocated(input any) LocatedNodeList
- func (p *Path) String() string
- func (p *Path) UnmarshalBinary(data []byte) error
- func (p *Path) UnmarshalText(data []byte) error
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrPathParse = parser.ErrPathParse
ErrPathParse errors are returned for path parse errors.
Functions ¶
This section is empty.
Types ¶
type LocatedNodeList ¶ added in v0.3.0
type LocatedNodeList []*spec.LocatedNode
LocatedNodeList is a list of nodes selected by a JSONPath query, along with their [NormalizedPath] locations. Returned by Path.SelectLocated.
Example ¶
package main import ( "fmt" "github.com/theory/jsonpath" ) func main() { // Load some JSON. menu := map[string]any{ "apps": map[string]any{ "guacamole": 19.99, "salsa": 5.99, }, } // Parse a JSONPath and select from the input. p := jsonpath.MustParse(`$.apps["salsa", "guacamole"]`) nodes := p.SelectLocated(menu) // Show the nodes. fmt.Println("Nodes:") for n := range nodes.Nodes() { fmt.Printf(" %v\n", n) } // Show the paths. fmt.Println("\nPaths:") for p := range nodes.Paths() { fmt.Printf(" %v\n", p) } }
Output: Nodes: 5.99 19.99 Paths: $['apps']['salsa'] $['apps']['guacamole']
func (LocatedNodeList) All ¶ added in v0.3.0
func (list LocatedNodeList) All() iter.Seq[*spec.LocatedNode]
All returns an iterator over all the nodes in list.
Range over list itself to get indexes and node values.
func (LocatedNodeList) Clone ¶ added in v0.3.0
func (list LocatedNodeList) Clone() LocatedNodeList
Clone returns a shallow copy of list.
Example ¶
package main import ( "fmt" "github.com/theory/jsonpath" ) func main() { // Load some JSON. items := []any{1, 2, 3, 4, 5} // Parse a JSONPath and select from the input. p := jsonpath.MustParse("$[2, 0, 1, 0, 1]") nodes := p.SelectLocated(items) // Clone the selected nodes then deduplicate. orig := nodes.Clone() nodes = nodes.Deduplicate() // Cloned nodes have the original count. fmt.Printf("Unique Count: %v\nOriginal Count: %v\n", len(nodes), len(orig)) }
Output: Unique Count: 3 Original Count: 5
func (LocatedNodeList) Deduplicate ¶ added in v0.3.0
func (list LocatedNodeList) Deduplicate() LocatedNodeList
Deduplicate deduplicates the nodes in list based on their [NormalizedPath] values, modifying the contents of list. It returns the modified list, which may have a shorter length, and zeroes the elements between the new length and the original length.
Example ¶
package main import ( "fmt" "github.com/theory/jsonpath" ) func main() { // Load some JSON. pallet := map[string]any{"colors": []any{"red", "blue"}} // Parse a JSONPath and select from the input. p := jsonpath.MustParse("$.colors[0, 1, 1, 0]") nodes := p.SelectLocated(pallet) fmt.Printf("Items: %v\n", len(nodes)) // Deduplicate nodes = nodes.Deduplicate() fmt.Printf("Items: %v\n", len(nodes)) }
Output: Items: 4 Items: 2
func (LocatedNodeList) Nodes ¶ added in v0.3.0
func (list LocatedNodeList) Nodes() iter.Seq[any]
Nodes returns an iterator over all the nodes in list. This is the same data as returned by Path.Select.
func (LocatedNodeList) Paths ¶ added in v0.3.0
func (list LocatedNodeList) Paths() iter.Seq[spec.NormalizedPath]
Paths returns an iterator over all the [NormalizedPath] values in list.
func (LocatedNodeList) Sort ¶ added in v0.3.0
func (list LocatedNodeList) Sort()
Sort sorts list by the [NormalizedPath] of each node.
Example ¶
package main import ( "fmt" "github.com/theory/jsonpath" ) func main() { // Load some JSON. pallet := map[string]any{"colors": []any{"red", "blue", "green"}} // Parse a JSONPath and select from the input. p := jsonpath.MustParse("$.colors[2, 0, 1]") nodes := p.SelectLocated(pallet) // Show selected. fmt.Println("Selected:") for _, node := range nodes { fmt.Printf(" %v: %v\n", node.Path, node.Node) } // Sort by normalized paths and show selected again. nodes.Sort() fmt.Println("\nSorted:") for _, node := range nodes { fmt.Printf(" %v: %v\n", node.Path, node.Node) } }
Output: Selected: $['colors'][2]: green $['colors'][0]: red $['colors'][1]: blue Sorted: $['colors'][0]: red $['colors'][1]: blue $['colors'][2]: green
type NodeList ¶ added in v0.3.0
type NodeList []any
NodeList is a list of nodes selected by a JSONPath query. Each node represents a single JSON value selected from the JSON query argument. Returned by Path.Select.
type Option ¶
type Option func(*Parser)
Option defines a parser option.
func WithRegistry ¶
WithRegistry configures a Parser with a registry.Registry, which may contain function extensions.
Example ¶
Use WithRegistry to create a Parser that uses a registry.Registry containing function extensions, as defined by the standard. This example creates a function named "first" that returns the first item in a list of nodes.
package main import ( "errors" "fmt" "log" "github.com/theory/jsonpath" "github.com/theory/jsonpath/registry" "github.com/theory/jsonpath/spec" ) func main() { // Register the first function. reg := registry.New() err := reg.Register( "first", // name spec.FuncValue, // returns a single value validateFirstArgs, // parse-time validation defined below firstFunc, // function defined below ) if err != nil { log.Fatalf("Error %v", err) } // Create a parser with the registry that contains the extension. parser := jsonpath.NewParser(jsonpath.WithRegistry(reg)) // Use the function to select lists that start with 6. path, err := parser.Parse("$[? first(@.*) == 6]") if err != nil { log.Fatalf("Error %v", err) } // Do any of these arrays start with 6? input := []any{ []any{1, 2, 3, 4, 5}, []any{6, 7, 8, 9}, []any{4, 8, 12}, } nodes := path.Select(input) fmt.Printf("%v\n", nodes) } // validateFirstArgs validates that a single argument is passed to the first() // function, and that it can be converted to [spec.NodesType], so that first() // can return the first node. It's called by the parser. func validateFirstArgs(args []spec.FuncExprArg) error { if len(args) != 1 { return fmt.Errorf("expected 1 argument but found %v", len(args)) } if !args[0].ConvertsTo(spec.FuncNodes) { return errors.New("cannot convert argument to nodes") } return nil } // firstFunc defines the custom first() JSONPath function. It converts its // single argument to a [spec.NodesType] value and returns a [spec.ValueType] // that contains the first node. If there are no nodes it returns nil. func firstFunc(jv []spec.PathValue) spec.PathValue { nodes := spec.NodesFrom(jv[0]) if len(nodes) == 0 { return nil } return spec.Value(nodes[0]) }
Output: [[6 7 8 9]]
type Parser ¶
type Parser struct {
// contains filtered or unexported fields
}
Parser parses JSONPath strings into Path values.
Example ¶
Use the Parser to parse a collection of paths.
package main import ( "encoding/json" "fmt" "log" "github.com/theory/jsonpath" ) func main() { // Create a new parser using the default function registry. parser := jsonpath.NewParser() // Parse a list of paths. paths := []*jsonpath.Path{} for _, path := range []string{ "$.store.book[*].author", "$..author", "$.store..color", "$..book[2].author", "$..book[2].publisher", "$..book[?@.isbn].title", "$..book[?@.price<10].title", } { p, err := parser.Parse(path) if err != nil { log.Fatal(err) } paths = append(paths, p) } // Later, use the paths to select from JSON inputs. store := bookstore() for _, p := range paths { items := p.Select(store) array, err := json.Marshal(items) if err != nil { log.Fatal(err) } fmt.Printf("%s\n", array) } } // bookstore returns an unmarshaled JSON object. func bookstore() any { src := []byte(`{ "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": 399 } } }`) var value any if err := json.Unmarshal(src, &value); err != nil { log.Fatal(err) } return value }
Output: ["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"] ["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"] ["red"] ["Herman Melville"] [] ["Moby Dick","The Lord of the Rings"] ["Sayings of the Century","Moby Dick"]
func (*Parser) MustParse ¶
MustParse parses path, a JSONPath query string, into a Path. Panics with an ErrPathParse on parse failure.
type Path ¶
type Path struct {
// contains filtered or unexported fields
}
Path represents a RFC 9535 JSONPath query.
func MustParse ¶
MustParse parses path into a Path. Panics with an ErrPathParse on parse failure.
func Parse ¶
Parse parses path, a JSONPath query string, into a Path. Returns an ErrPathParse on parse failure.
func (*Path) MarshalBinary ¶ added in v0.10.0
MarshalBinary encodes p into UTF-8-encoded bytes and returns the result. Implements encoding.BinaryMarshaler.
func (*Path) MarshalText ¶ added in v0.10.0
MarshalText encodes p into UTF-8-encoded text and returns the result. Implements encoding.TextMarshaler.
func (*Path) Select ¶
Select returns the nodes that JSONPath query p selects from input.
Example ¶
package main import ( "fmt" "github.com/theory/jsonpath" ) func main() { // Load some JSON. menu := map[string]any{ "apps": map[string]any{ "guacamole": 19.99, "salsa": 5.99, }, } // Parse a JSONPath and select from the input. p := jsonpath.MustParse("$.apps.*") nodes := p.Select(menu) // Show the selected values. for node := range nodes.All() { fmt.Printf("%v\n", node) } }
Output: 19.99 5.99
func (*Path) SelectLocated ¶ added in v0.3.0
func (p *Path) SelectLocated(input any) LocatedNodeList
SelectLocated returns the nodes that JSONPath query p selects from input as spec.LocatedNode values that pair the nodes with the normalized paths that identify them. Unless you have a specific need for the unique spec.NormalizedPath for each value, you probably want to use Path.Select.
Example ¶
package main import ( "fmt" "github.com/theory/jsonpath" ) func main() { // Load some JSON. menu := map[string]any{ "apps": map[string]any{ "guacamole": 19.99, "salsa": 5.99, }, } // Parse a JSONPath and select from the input. p := jsonpath.MustParse("$.apps.*") nodes := p.SelectLocated(menu) // Show the selected nodes. for node := range nodes.All() { fmt.Printf("%v: %v\n", node.Path, node.Node) } }
Output: $['apps']['guacamole']: 19.99 $['apps']['salsa']: 5.99
func (*Path) UnmarshalBinary ¶ added in v0.10.0
UnmarshalBinary decodes UTF-8-encoded bytes into p. Implements encoding.BinaryUnmarshaler.
func (*Path) UnmarshalText ¶ added in v0.10.0
UnmarshalText decodes UTF-8-encoded text into p. Implements encoding.TextUnmarshaler.
Directories
¶
Path | Synopsis |
---|---|
internal
|
|
wasm
Package main performs a basic JSONPath query in order to test WASM compilation.
|
Package main performs a basic JSONPath query in order to test WASM compilation. |
Package parser parses RFC 9535 JSONPath queries into parse trees.
|
Package parser parses RFC 9535 JSONPath queries into parse trees. |
Package registry provides a RFC 9535 JSONPath function extension registry.
|
Package registry provides a RFC 9535 JSONPath function extension registry. |
Package spec provides the [RFC 9535 JSONPath] [AST] and execution for github.com/theory/jsonpath.
|
Package spec provides the [RFC 9535 JSONPath] [AST] and execution for github.com/theory/jsonpath. |