Documentation
¶
Overview ¶
Package jsonpath implements JSONPath query syntax parser and evaluator with gjson-style API.
The implementation follows RFC 9535: https://www.rfc-editor.org/rfc/rfc9535.html
Index ¶
- Constants
- Variables
- type CompOp
- type Comparable
- type ComparableType
- type Comparison
- type Evaluator
- type FilterExpr
- type FilterExprType
- type FilterQuery
- type FuncArg
- type FuncArgType
- type FuncCall
- type FunctionSignature
- type FunctionValueType
- type JSONType
- type KV
- type Lexer
- type LiteralType
- type LiteralValue
- type Parser
- type Query
- type Result
- func (r Result) Array() []Result
- func (r Result) Bool() bool
- func (r Result) Exists() bool
- func (r Result) Float() float64
- func (r Result) Get(path string) Result
- func (r Result) GetMany(path string) []Result
- func (r Result) Int() int64
- func (r Result) IsArray() bool
- func (r Result) IsBool() bool
- func (r Result) IsObject() bool
- func (r Result) IsString() bool
- func (r Result) Map() map[string]Result
- func (r Result) MapKVList() []KV
- func (r Result) String() string
- func (r Result) Uint() uint64
- func (r Result) Value() interface{}
- type Segment
- type SegmentType
- type Selector
- type SelectorType
- type SingularQuery
- type SingularSegment
- type SingularSegmentType
- type SliceParams
- type TestExpr
- type Token
- type TokenType
Examples ¶
Constants ¶
const ( MinSafeInteger = -(2<<52 - 1) MaxSafeInteger = 2<<52 - 1 )
I-JSON safe integer range
Variables ¶
var FunctionValueNothing = Result{}
Functions ¶
This section is empty.
Types ¶
type Comparable ¶
type Comparable struct {
Type ComparableType
Literal *LiteralValue
SingularQuery *SingularQuery
FuncExpr *FuncCall
}
Comparable is one side of a comparison.
type ComparableType ¶
type ComparableType int
ComparableType identifies what a comparable holds.
const ( ComparableLiteral ComparableType = iota ComparableSingularQuery ComparableFuncExpr )
type Comparison ¶
type Comparison struct {
Left *Comparable
Op CompOp
Right *Comparable
}
Comparison represents a comparison expression.
type Evaluator ¶
type Evaluator struct {
// contains filtered or unexported fields
}
Evaluator evaluates JSONPath expressions against JSON data
func NewEvaluator ¶
NewEvaluator creates a new evaluator for the given JSON and query
type FilterExpr ¶
type FilterExpr struct {
Type FilterExprType
Left *FilterExpr
Right *FilterExpr
Operand *FilterExpr
Comp *Comparison
Test *TestExpr
}
FilterExpr represents a filter expression.
type FilterExprType ¶
type FilterExprType int
FilterExprType identifies the type of filter expression.
const ( FilterLogicalOr FilterExprType = iota // left || right FilterLogicalAnd // left && right FilterLogicalNot // !operand FilterParen // (operand) FilterComparison // comparison FilterTest // test expression )
type FilterQuery ¶
type FilterQuery struct {
Relative bool // true = starts with @, false = starts with $
Segments []*Segment
}
FilterQuery is a query used in a filter (relative or absolute)
type FuncArg ¶
type FuncArg struct {
Type FuncArgType
Literal *LiteralValue
FilterQuery *FilterQuery
LogicalExpr *FilterExpr
FuncExpr *FuncCall
}
FuncArg represents a function argument
type FuncArgType ¶
type FuncArgType int
FuncArgType identifies the type of function argument
const ( FuncArgLiteral FuncArgType = iota FuncArgFilterQuery FuncArgLogicalExpr FuncArgFuncExpr )
type FunctionSignature ¶ added in v0.2.0
type FunctionSignature struct {
Name string
ParamTypes []FunctionValueType
ReturnType FunctionValueType
Handler func(args []interface{}) (interface{}, error)
}
FunctionSignature 定义函数签名
type FunctionValueType ¶ added in v0.2.0
type FunctionValueType int
FunctionValueType 表示函数参数/返回值的类型
const ( FunctionValueTypeValue FunctionValueType = iota // Result / Noting FunctionValueTypeLogical // true/false FunctionValueTypeNodes // []Result )
func (FunctionValueType) String ¶ added in v0.2.0
func (t FunctionValueType) String() string
String 返回类型的字符串表示
type JSONType ¶
type JSONType int
JSONType represents the type of a JSON value
const ( // JSONTypeNull is a null json value JSONTypeNull JSONType = iota // JSONTypeFalse is a json false boolean JSONTypeFalse // JSONTypeNumber is json number JSONTypeNumber // JSONTypeString is json string JSONTypeString // JSONTypeTrue is a json true boolean JSONTypeTrue // JSONTypeJSON is a raw block of JSON JSONTypeJSON )
type Lexer ¶
type Lexer struct {
// contains filtered or unexported fields
}
Lexer tokenizes JSONPath expressions
type LiteralType ¶
type LiteralType int
const ( LiteralString LiteralType = iota LiteralNumber LiteralTrue LiteralFalse LiteralNull )
type LiteralValue ¶
type LiteralValue struct {
Type LiteralType
Value string
}
LiteralValue represents a literal value in expressions
type Parser ¶
type Parser struct {
// contains filtered or unexported fields
}
Parser parses JSONPath expressions into an AST
type Query ¶
type Query struct {
Segments []*Segment
}
Query represents a JSONPath query: $ followed by segments.
type Result ¶
type Result struct {
// Type is the json type
Type JSONType
// Raw is the raw json
Raw string
// Str is the json string
Str string
// Num is the json number
Num float64
// Index of raw value in original json, zero means index unknown
Index int
}
Result represents a JSON value returned from Get()
func GetMany ¶
GetMany executes a JSONPath query and returns all results
Example ¶
package main
import (
"fmt"
"github.com/saltfishpr/jsonpath"
)
var rfcExampleJSON = `{
"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}
}
}`
func main() {
fmt.Println("1. the authors of all books in the store")
r := jsonpath.GetMany(rfcExampleJSON, "$.store.book[*].author")
for _, v := range r {
fmt.Println(v.Value())
}
fmt.Println("\n2. all authors")
r = jsonpath.GetMany(rfcExampleJSON, "$..author")
for _, v := range r {
fmt.Println(v.Value())
}
fmt.Println("\n3. all things in the store, which are some books and a red bicycle")
r = jsonpath.GetMany(rfcExampleJSON, "$.store.*")
for _, v := range r {
fmt.Println(v.Value())
}
fmt.Println("\n4. the prices of everything in the store")
r = jsonpath.GetMany(rfcExampleJSON, "$.store..price")
for _, v := range r {
fmt.Println(v.Value())
}
fmt.Println("\n5. the third book")
r = jsonpath.GetMany(rfcExampleJSON, "$..book[2]")
for _, v := range r {
fmt.Println(v.Value())
}
fmt.Println("\n6. the third book's author")
r = jsonpath.GetMany(rfcExampleJSON, "$..book[2].author")
for _, v := range r {
fmt.Println(v.Value())
}
fmt.Println("\n7. empty result: the third book does not have a \"publisher\" member")
r = jsonpath.GetMany(rfcExampleJSON, "$..book[2].publisher")
for _, v := range r {
fmt.Println(v.Value())
}
fmt.Println("\n8. the last book in order")
r = jsonpath.GetMany(rfcExampleJSON, "$..book[-1]")
for _, v := range r {
fmt.Println(v.Value())
}
fmt.Println("\n9. the first two books")
r = jsonpath.GetMany(rfcExampleJSON, "$..book[:2]")
for _, v := range r {
fmt.Println(v.Value())
}
r = jsonpath.GetMany(rfcExampleJSON, "$..book[0,1]")
for _, v := range r {
fmt.Println(v.Value())
}
fmt.Println("\n10. all books with an ISBN number")
r = jsonpath.GetMany(rfcExampleJSON, "$..book[?(@.isbn)]")
for _, v := range r {
fmt.Println(v.Value())
}
fmt.Println("\n11. all books cheaper than 10")
r = jsonpath.GetMany(rfcExampleJSON, "$..book[?(@.price<10)]")
for _, v := range r {
fmt.Println(v.Value())
}
fmt.Println("\n12. all member values and array elements contained in the input value")
r = jsonpath.GetMany(rfcExampleJSON, "$..*")
for _, v := range r {
fmt.Println(v.Value())
}
}
Output: 1. the authors of all books in the store Nigel Rees Evelyn Waugh Herman Melville J. R. R. Tolkien 2. all authors Nigel Rees Evelyn Waugh Herman Melville J. R. R. Tolkien 3. all things in the store, which are some books and a red bicycle [{"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}] map[color:red price:399] 4. the prices of everything in the store 8.95 12.99 8.99 22.99 399 5. the third book map[author:Herman Melville category:fiction isbn:0-553-21311-3 price:8.99 title:Moby Dick] 6. the third book's author Herman Melville 7. empty result: the third book does not have a "publisher" member 8. the last book in order map[author:J. R. R. Tolkien category:fiction isbn:0-395-19395-8 price:22.99 title:The Lord of the Rings] 9. the first two books map[author:Nigel Rees category:reference price:8.95 title:Sayings of the Century] map[author:Evelyn Waugh category:fiction price:12.99 title:Sword of Honour] map[author:Nigel Rees category:reference price:8.95 title:Sayings of the Century] map[author:Evelyn Waugh category:fiction price:12.99 title:Sword of Honour] 10. all books with an ISBN number map[author:Herman Melville category:fiction isbn:0-553-21311-3 price:8.99 title:Moby Dick] map[author:J. R. R. Tolkien category:fiction isbn:0-395-19395-8 price:22.99 title:The Lord of the Rings] 11. all books cheaper than 10 map[author:Nigel Rees category:reference price:8.95 title:Sayings of the Century] map[author:Herman Melville category:fiction isbn:0-553-21311-3 price:8.99 title:Moby Dick] 12. all member values and array elements contained in the input value map[bicycle:{"color": "red", "price": 399} 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} ]] [{"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}] map[color:red price:399] map[author:Nigel Rees category:reference price:8.95 title:Sayings of the Century] map[author:Evelyn Waugh category:fiction price:12.99 title:Sword of Honour] map[author:Herman Melville category:fiction isbn:0-553-21311-3 price:8.99 title:Moby Dick] map[author:J. R. R. Tolkien category:fiction isbn:0-395-19395-8 price:22.99 title:The Lord of the Rings] reference Nigel Rees Sayings of the Century 8.95 fiction Evelyn Waugh Sword of Honour 12.99 fiction Herman Melville Moby Dick 0-553-21311-3 8.99 fiction J. R. R. Tolkien The Lord of the Rings 0-395-19395-8 22.99 red 399
Example (Functions) ¶
package main
import (
"fmt"
"github.com/saltfishpr/jsonpath"
)
var rfcExampleJSON = `{
"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}
}
}`
func main() {
// length() 函数示例 - 计算值的长度
fmt.Println("1. length() - 计算数组元素的个数")
r := jsonpath.GetMany(rfcExampleJSON, "$.store.book[?length(@.category) == 9]")
for _, v := range r {
fmt.Println(v.Value())
}
fmt.Println("\n2. length() - 筛选有 4 个成员的对象(有 isbn 字段的书)")
r = jsonpath.GetMany(rfcExampleJSON, "$.store.book[?length(@) == 4]")
for _, v := range r {
fmt.Println(v.Value())
}
// count() 函数示例 - 计算节点列表中的节点数量
fmt.Println("\n3. count() - 检查所有属性数量是否等于 2")
r = jsonpath.GetMany(rfcExampleJSON, "$.store[?count(@.*) == 2]")
for _, v := range r {
fmt.Println(v.Value())
}
// value() 函数示例 - 将节点列表转换为值
fmt.Println("\n4. value() - 获取 descendant nodes 中唯一值为 'red' 的节点")
r = jsonpath.GetMany(rfcExampleJSON, "$.store[?value(@..color) == \"red\"]")
for _, v := range r {
fmt.Println(v.Value())
}
// 添加更多示例数据的 JSON
functionsExampleJSON := `{
"users": [
{"name": "Bob", "email": "[email protected]", "role": "admin"},
{"name": "Alice", "email": "[email protected]", "role": "user"},
{"name": "Rob", "email": "[email protected]", "role": "user"}
],
"products": [
{"id": "A001", "name": "Apple", "category": "fruit"},
{"id": "B002", "name": "Banana", "category": "fruit"},
{"id": "C003", "name": "Carrot", "category": "vegetable"}
],
"dates": ["2024-01-15", "2024-02-20", "2024-03-25"]
}`
// match() 函数示例 - 完全匹配正则表达式
fmt.Println("\n5. match() - 匹配以 2024-02 开头的日期")
r = jsonpath.GetMany(functionsExampleJSON, "$.dates[?match(@, '2024-02-..')]")
for _, v := range r {
fmt.Println(v.Value())
}
fmt.Println("\n6. match() - 匹配以 example.com 结尾的邮箱")
r = jsonpath.GetMany(functionsExampleJSON, "$.users[?match(@.email, '.*@example.com')]")
for _, v := range r {
fmt.Println(v.Value())
}
// search() 函数示例 - 搜索包含匹配正则表达式的子串
fmt.Println("\n7. search() - 名字包含 [BR]ob 的用户")
r = jsonpath.GetMany(functionsExampleJSON, "$.users[?search(@.name, '[BR]ob')]")
for _, v := range r {
fmt.Println(v.Value())
}
fmt.Println("\n8. search() - ID 包含数字 0 的产品")
r = jsonpath.GetMany(functionsExampleJSON, "$.products[?search(@.id, '0')]")
for _, v := range r {
fmt.Println(v.Value())
}
fmt.Println("\n9. search() - 类别包含 'e' 的产品")
r = jsonpath.GetMany(functionsExampleJSON, "$.products[?search(@.category, 'e')]")
for _, v := range r {
fmt.Println(v.Value())
}
}
Output: 1. length() - 计算数组元素的个数 map[author:Nigel Rees category:reference price:8.95 title:Sayings of the Century] 2. length() - 筛选有 4 个成员的对象(有 isbn 字段的书) map[author:Nigel Rees category:reference price:8.95 title:Sayings of the Century] map[author:Evelyn Waugh category:fiction price:12.99 title:Sword of Honour] 3. count() - 检查所有属性数量是否等于 2 map[color:red price:399] 4. value() - 获取 descendant nodes 中唯一值为 'red' 的节点 map[color:red price:399] 5. match() - 匹配以 2024-02 开头的日期 2024-02-20 6. match() - 匹配以 example.com 结尾的邮箱 map[email:[email protected] name:Bob role:admin] map[email:[email protected] name:Alice role:user] map[email:[email protected] name:Rob role:user] 7. search() - 名字包含 [BR]ob 的用户 map[email:[email protected] name:Bob role:admin] map[email:[email protected] name:Rob role:user] 8. search() - ID 包含数字 0 的产品 map[category:fruit id:A001 name:Apple] map[category:fruit id:B002 name:Banana] map[category:vegetable id:C003 name:Carrot] 9. search() - 类别包含 'e' 的产品 map[category:vegetable id:C003 name:Carrot]
func GetManyBytes ¶
GetManyBytes executes a JSONPath query with []byte input
type Segment ¶
type Segment struct {
Type SegmentType
Selectors []*Selector
}
Segment is a child or descendant segment containing selectors.
type SegmentType ¶
type SegmentType int
SegmentType distinguishes child vs descendant segments.
const ( ChildSegment SegmentType = iota DescendantSegment )
type Selector ¶
type Selector struct {
Type SelectorType
Name string // for NameSelector
Index int // for IndexSelector
Slice *SliceParams // for SliceSelector
Filter *FilterExpr // for FilterSelector
}
Selector represents a single selector within a segment.
type SelectorType ¶
type SelectorType int
SelectorType distinguishes different selector types.
const ( NameSelector SelectorType = iota // 'name' or "name" WildcardSelector // * IndexSelector // integer index SliceSelector // start:end:step FilterSelector // ?<logical-expr> )
type SingularQuery ¶
type SingularQuery struct {
Relative bool // true = starts with @, false = starts with $
Segments []*SingularSegment
}
SingularQuery is a query that produces at most one node
type SingularSegment ¶
type SingularSegment struct {
Type SingularSegmentType
Name string
Index int
}
SingularSegment is a name or index segment in a singular query
type SingularSegmentType ¶
type SingularSegmentType int
const ( SingularNameSegment SingularSegmentType = iota SingularIndexSegment )
type SliceParams ¶
SliceParams holds start:end:step for a slice selector.
type TestExpr ¶
type TestExpr struct {
FilterQuery *FilterQuery
FuncExpr *FuncCall
}
TestExpr represents a test expression (existence or function)
type TokenType ¶
type TokenType int
TokenType is the type of a token
const ( TokenIllegal TokenType = iota TokenEOF // Identifiers TokenRoot // $ - Root node identifier TokenCurrent // @ - Current node identifier // Operators TokenDot // . - Dot (child segment shorthand) TokenDotDot // .. - Double dot (descendant segment) TokenLBracket // [ - Left bracket TokenRBracket // ] - Right bracket TokenComma // , - Comma TokenQuestion // ? - Question mark (filter) TokenColon // : - Colon (slice) TokenWildcard // * - Wildcard // Comparison operators TokenEq // == - Equal TokenNe // != - Not equal TokenLt // < - Less than TokenLe // <= - Less than or equal TokenGt // > - Greater than TokenGe // >= - Greater than or equal // Logical operators TokenLAnd // && - Logical and TokenLOr // || - Logical or TokenLNot // ! - Logical not // Parentheses TokenLParen // ( - Left parenthesis TokenRParen // ) - Right parenthesis // Literals TokenIdent // Identifier/name/function name TokenNumber // Number TokenString // String TokenTrue // true TokenFalse // false TokenNull // null )
Token type constants