Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions errors/error_basic_runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,10 @@ func (e *ErrorBasicRuntime) GetPath() string {
func (e *ErrorBasicRuntime) GetRemainingPathLen() int {
return e.remainingPathLen
}

func NewErrorBasicRuntime(path string, remainingPathLen int) ErrorBasicRuntime {
return ErrorBasicRuntime{
path: path,
remainingPathLen: remainingPathLen,
}
}
8 changes: 4 additions & 4 deletions errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ func (e ErrorTypeUnmatched) Error() string {
return fmt.Sprintf(`type unmatched (path=%s, expected=%s, found=%s)`, e.ErrorBasicRuntime.GetPath(), e.ExpectedType, e.FoundType)
}

func NewErrorTypeUnmatched(path string, remainingPathLen int, expected string, found string) ErrorTypeUnmatched {
func NewErrorTypeUnmatched(errBasicRuntime *ErrorBasicRuntime, expected string, found string) ErrorTypeUnmatched {
return ErrorTypeUnmatched{
ErrorBasicRuntime: &ErrorBasicRuntime{path: path, remainingPathLen: remainingPathLen},
ErrorBasicRuntime: errBasicRuntime,
ExpectedType: expected,
FoundType: found,
}
Expand All @@ -98,9 +98,9 @@ func (e ErrorMemberNotExist) Error() string {
return fmt.Sprintf(`member did not exist (path=%s)`, e.ErrorBasicRuntime.GetPath())
}

func NewErrorMemberNotExist(path string, remainingPathLen int) ErrorMemberNotExist {
func NewErrorMemberNotExist(errBasicRuntime *ErrorBasicRuntime) ErrorMemberNotExist {
return ErrorMemberNotExist{
ErrorBasicRuntime: &ErrorBasicRuntime{path: path, remainingPathLen: remainingPathLen},
ErrorBasicRuntime: errBasicRuntime,
}
}

Expand Down
4 changes: 0 additions & 4 deletions internal/syntax/jsonpath.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
package syntax

import (
"regexp"
"sync"

"github.com/AsaiYusuke/jsonpath/v2/config"
)

var parseMutex sync.Mutex
var parser = pegJSONPathParser[uint32]{}
var unescapeRegex = regexp.MustCompile(`\\(.)`)

// Retrieve returns the retrieved JSON using the given JSONPath.
func Retrieve(jsonPath string, src any, config ...config.Config) ([]any, error) {
Expand Down Expand Up @@ -42,8 +40,6 @@ func Parse(jsonPath string, config ...config.Config) (f func(src any, dst ...*[]
parser.Reset()
}

parser.jsonPathParser.unescapeRegex = unescapeRegex

if len(config) > 0 {
parser.jsonPathParser.filterFunctions = config[0].FilterFunctions
parser.jsonPathParser.aggregateFunctions = config[0].AggregateFunctions
Expand Down
7 changes: 4 additions & 3 deletions internal/syntax/jsonpath_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ import (
"github.com/AsaiYusuke/jsonpath/v2/errors"
)

var unescapeRegex = regexp.MustCompile(`\\(.)`)

type jsonPathParser struct {
root syntaxNode
paramsList [][]any
params []any
unescapeRegex *regexp.Regexp
filterFunctions map[string]func(any) (any, error)
aggregateFunctions map[string]func([]any) (any, error)
accessorMode bool
Expand Down Expand Up @@ -59,8 +60,8 @@ func (p *jsonPathParser) toFloat(text string) float64 {
}

func (p *jsonPathParser) unescape(text string) string {
return p.unescapeRegex.ReplaceAllStringFunc(text, func(block string) string {
varBlockSet := p.unescapeRegex.FindStringSubmatch(block)
return unescapeRegex.ReplaceAllStringFunc(text, func(block string) string {
varBlockSet := unescapeRegex.FindStringSubmatch(block)
return varBlockSet[1]
})
}
Expand Down
41 changes: 31 additions & 10 deletions internal/syntax/syntax_basic_node.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
package syntax

import (
"reflect"
"sync"

"github.com/AsaiYusuke/jsonpath/v2/config"
"github.com/AsaiYusuke/jsonpath/v2/errors"
)

type syntaxNodeErrState struct {
basicRuntime errors.ErrorBasicRuntime
}

type syntaxBasicNode struct {
path string
remainingPath string
remainingPathLen int
valueGroup bool
next syntaxNode
accessorMode bool
preErrMemberNotExist errors.ErrorMemberNotExist
path string
remainingPath string
remainingPathLen int
valueGroup bool
next syntaxNode
accessorMode bool
errState *syntaxNodeErrState
onceErrState sync.Once
}

func (i *syntaxBasicNode) setPath(path string) {
Expand Down Expand Up @@ -52,11 +60,24 @@ func (i *syntaxBasicNode) getNext() syntaxNode {
return i.next
}

func (i *syntaxBasicNode) ensureErrState() {
i.onceErrState.Do(func() {
i.errState = &syntaxNodeErrState{}
i.errState.basicRuntime = errors.NewErrorBasicRuntime(i.path, i.remainingPathLen)
})
}

func (i *syntaxBasicNode) newErrMemberNotExist() errors.ErrorMemberNotExist {
if i.preErrMemberNotExist.ErrorBasicRuntime == nil {
i.preErrMemberNotExist = errors.NewErrorMemberNotExist(i.path, i.remainingPathLen)
i.ensureErrState()
return errors.NewErrorMemberNotExist(&i.errState.basicRuntime)
}

func (i *syntaxBasicNode) newErrTypeUnmatched(expected string, current any) errors.ErrorTypeUnmatched {
i.ensureErrState()
if current != nil {
return errors.NewErrorTypeUnmatched(&i.errState.basicRuntime, expected, reflect.TypeOf(current).String())
}
return i.preErrMemberNotExist
return errors.NewErrorTypeUnmatched(&i.errState.basicRuntime, expected, msgTypeNull)
}

func (i *syntaxBasicNode) retrieveAnyValueNext(
Expand Down
8 changes: 4 additions & 4 deletions internal/syntax/syntax_compare_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ func (q *syntaxCompareQuery) compute(
}
}

rightValues := q.rightParam.compute(root, currentList)

// The syntax parser always results in a literal value on the right side as input.
if q.comparator.comparator(leftValues, rightValues[0]) {
rightValue := q.rightParam.compute(root, currentList)[0]

if q.comparator.compare(leftValues, rightValue) {
return leftValues
}

if len(leftValues) == 1 && leftValues[0] == emptyEntity && rightValues[0] == emptyEntity {
if len(leftValues) == 1 && leftValues[0] == emptyEntity && rightValue == emptyEntity {
if _, ok := q.comparator.(*syntaxCompareDeepEQ); ok {
return currentList
}
Expand Down
2 changes: 1 addition & 1 deletion internal/syntax/syntax_compare_query_comparator_deep_eq.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import "reflect"
type syntaxCompareDeepEQ struct {
}

func (c *syntaxCompareDeepEQ) comparator(left []any, right any) bool {
func (c *syntaxCompareDeepEQ) compare(left []any, right any) bool {
var hasValue bool
for leftIndex := range left {
if left[leftIndex] == emptyEntity {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import "encoding/json"
type syntaxCompareDirectEQ struct {
}

func (c *syntaxCompareDirectEQ) comparator(left []any, right any) bool {
func (c *syntaxCompareDirectEQ) compare(left []any, right any) bool {
var hasValue bool
for leftIndex := range left {
if left[leftIndex] == emptyEntity {
Expand Down
2 changes: 1 addition & 1 deletion internal/syntax/syntax_compare_query_comparator_ge.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import "encoding/json"
type syntaxCompareGE struct {
}

func (c *syntaxCompareGE) comparator(left []any, right any) bool {
func (c *syntaxCompareGE) compare(left []any, right any) bool {
rightFloatValue, rightIsFloat := right.(float64)
rightNumberValue, rightIsNumber := right.(json.Number)
rightStringValue, rightIsString := right.(string)
Expand Down
2 changes: 1 addition & 1 deletion internal/syntax/syntax_compare_query_comparator_gt.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import "encoding/json"
type syntaxCompareGT struct {
}

func (c *syntaxCompareGT) comparator(left []any, right any) bool {
func (c *syntaxCompareGT) compare(left []any, right any) bool {
rightFloat, rightIsFloat := right.(float64)
rightNumber, rightIsNumber := right.(json.Number)
rightString, rightIsString := right.(string)
Expand Down
2 changes: 1 addition & 1 deletion internal/syntax/syntax_compare_query_comparator_le.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import "encoding/json"
type syntaxCompareLE struct {
}

func (c *syntaxCompareLE) comparator(left []any, right any) bool {
func (c *syntaxCompareLE) compare(left []any, right any) bool {
rightFloat, rightIsFloat := right.(float64)
rightNumber, rightIsNumber := right.(json.Number)
rightString, rightIsString := right.(string)
Expand Down
2 changes: 1 addition & 1 deletion internal/syntax/syntax_compare_query_comparator_lt.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import "encoding/json"
type syntaxCompareLT struct {
}

func (c *syntaxCompareLT) comparator(left []any, right any) bool {
func (c *syntaxCompareLT) compare(left []any, right any) bool {
rightFloat, rightIsFloat := right.(float64)
rightNumber, rightIsNumber := right.(json.Number)
rightString, rightIsString := right.(string)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import "encoding/json"
type syntaxCompareNumberGE struct {
}

func (c *syntaxCompareNumberGE) comparator(left []any, right any) bool {
func (c *syntaxCompareNumberGE) compare(left []any, right any) bool {
rightFloatValue, _ := right.(float64)

var hasValue bool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import "encoding/json"
type syntaxCompareNumberGT struct {
}

func (c *syntaxCompareNumberGT) comparator(left []any, right any) bool {
func (c *syntaxCompareNumberGT) compare(left []any, right any) bool {
rightFloatValue, _ := right.(float64)

var hasValue bool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import "encoding/json"
type syntaxCompareNumberLE struct {
}

func (c *syntaxCompareNumberLE) comparator(left []any, right any) bool {
func (c *syntaxCompareNumberLE) compare(left []any, right any) bool {
rightFloatValue, _ := right.(float64)

var hasValue bool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import "encoding/json"
type syntaxCompareNumberLT struct {
}

func (c *syntaxCompareNumberLT) comparator(left []any, right any) bool {
func (c *syntaxCompareNumberLT) compare(left []any, right any) bool {
rightFloatValue, _ := right.(float64)

var hasValue bool
Expand Down
2 changes: 1 addition & 1 deletion internal/syntax/syntax_compare_query_comparator_regex.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ type syntaxCompareRegex struct {
regex *regexp.Regexp
}

func (r *syntaxCompareRegex) comparator(left []any, _ any) bool {
func (r *syntaxCompareRegex) compare(left []any, _ any) bool {
var hasValue bool
for leftIndex := range left {
if left[leftIndex] == emptyEntity {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package syntax
type syntaxCompareStringGE struct {
}

func (c *syntaxCompareStringGE) comparator(left []any, right any) bool {
func (c *syntaxCompareStringGE) compare(left []any, right any) bool {
rightStringValue, _ := right.(string)

var hasValue bool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package syntax
type syntaxCompareStringGT struct {
}

func (c *syntaxCompareStringGT) comparator(left []any, right any) bool {
func (c *syntaxCompareStringGT) compare(left []any, right any) bool {
rightStringValue, _ := right.(string)

var hasValue bool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package syntax
type syntaxCompareStringLE struct {
}

func (c *syntaxCompareStringLE) comparator(left []any, right any) bool {
func (c *syntaxCompareStringLE) compare(left []any, right any) bool {
rightStringValue, _ := right.(string)

var hasValue bool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package syntax
type syntaxCompareStringLT struct {
}

func (c *syntaxCompareStringLT) comparator(left []any, right any) bool {
func (c *syntaxCompareStringLT) compare(left []any, right any) bool {
rightStringValue, _ := right.(string)

var hasValue bool
Expand Down
2 changes: 1 addition & 1 deletion internal/syntax/syntax_if_comparator.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package syntax

type syntaxComparator interface {
comparator(left []any, right any) bool
compare(left []any, right any) bool
}
9 changes: 1 addition & 8 deletions internal/syntax/syntax_node_identifier_child_multi.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package syntax

import (
"reflect"

"github.com/AsaiYusuke/jsonpath/v2/errors"
)

Expand Down Expand Up @@ -30,12 +28,7 @@ func (i *syntaxChildMultiIdentifier) retrieve(
return i.retrieveMap(root, srcMap, results)
}

if current != nil {
return errors.NewErrorTypeUnmatched(
i.path, i.remainingPathLen, msgTypeObject, reflect.TypeOf(current).String())
}
return errors.NewErrorTypeUnmatched(
i.path, i.remainingPathLen, msgTypeObject, msgTypeNull)
return i.newErrTypeUnmatched(msgTypeObject, current)
}

func (i *syntaxChildMultiIdentifier) retrieveMap(
Expand Down
9 changes: 1 addition & 8 deletions internal/syntax/syntax_node_identifier_child_single.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package syntax

import (
"reflect"

"github.com/AsaiYusuke/jsonpath/v2/errors"
)

Expand All @@ -19,10 +17,5 @@ func (i *syntaxChildSingleIdentifier) retrieve(
return i.retrieveMapNext(root, srcMap, i.identifier, results)
}

if current != nil {
return errors.NewErrorTypeUnmatched(
i.path, i.remainingPathLen, msgTypeObject, reflect.TypeOf(current).String())
}
return errors.NewErrorTypeUnmatched(
i.path, i.remainingPathLen, msgTypeObject, msgTypeNull)
return i.newErrTypeUnmatched(msgTypeObject, current)
}
9 changes: 1 addition & 8 deletions internal/syntax/syntax_node_identifier_child_wildcard.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package syntax

import (
"reflect"

"github.com/AsaiYusuke/jsonpath/v2/errors"
)

Expand All @@ -21,12 +19,7 @@ func (i *syntaxChildWildcardIdentifier) retrieve(
return i.retrieveList(root, typedNodes, results)

default:
if current != nil {
return errors.NewErrorTypeUnmatched(
i.path, i.remainingPathLen, msgTypeObjectOrArray, reflect.TypeOf(current).String())
}
return errors.NewErrorTypeUnmatched(
i.path, i.remainingPathLen, msgTypeObjectOrArray, msgTypeNull)
return i.newErrTypeUnmatched(msgTypeObjectOrArray, current)
}
}

Expand Down
8 changes: 1 addition & 7 deletions internal/syntax/syntax_node_identifier_recursive_child.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package syntax

import (
"reflect"
"slices"

"github.com/AsaiYusuke/jsonpath/v2/errors"
Expand All @@ -20,12 +19,7 @@ func (i *syntaxRecursiveChildIdentifier) retrieve(
switch current.(type) {
case map[string]any, []any:
default:
if current != nil {
return errors.NewErrorTypeUnmatched(
i.path, i.remainingPathLen, msgTypeObjectOrArray, reflect.TypeOf(current).String())
}
return errors.NewErrorTypeUnmatched(
i.path, i.remainingPathLen, msgTypeObjectOrArray, msgTypeNull)
return i.newErrTypeUnmatched(msgTypeObjectOrArray, current)
}

var deepestError errors.ErrorRuntime
Expand Down
Loading