@@ -14,34 +14,72 @@ import (
1414var ErrGetFromNullObj = errors .New ("get attribute from null object" )
1515
1616func JsonPathLookup (obj interface {}, jpath string ) (interface {}, error ) {
17- steps , err := tokenize (jpath )
17+ c , err := Compile (jpath )
1818 if err != nil {
1919 return nil , err
2020 }
21- if steps [0 ] != "@" && steps [0 ] != "$" {
21+ return c .Lookup (obj )
22+ }
23+
24+ type Compiled struct {
25+ path string
26+ steps []step
27+ }
28+
29+ type step struct {
30+ op string
31+ key string
32+ args interface {}
33+ }
34+
35+ func Compile (jpath string ) (* Compiled , error ) {
36+ tokens , err := tokenize (jpath )
37+ if err != nil {
38+ return nil , err
39+ }
40+ if tokens [0 ] != "@" && tokens [0 ] != "$" {
2241 return nil , fmt .Errorf ("$ or @ should in front of path" )
2342 }
24- steps = steps [1 :]
25- for _ , s := range steps {
26- op , key , args , err := parse_token (s )
43+ tokens = tokens [1 :]
44+ res := Compiled {
45+ path : jpath ,
46+ steps : make ([]step , len (tokens )),
47+ }
48+ for i , token := range tokens {
49+ op , key , args , err := parse_token (token )
50+ if err != nil {
51+ return nil , err
52+ }
53+ res .steps [i ] = step {op , key , args }
54+ }
55+ return & res , nil
56+ }
57+
58+ func (c * Compiled ) String () string {
59+ return fmt .Sprintf ("Compiled lookup: %s" , c .path )
60+ }
61+
62+ func (c * Compiled ) Lookup (obj interface {}) (interface {}, error ) {
63+ var err error
64+ for _ , s := range c .steps {
2765 // "key", "idx"
28- switch op {
66+ switch s . op {
2967 case "key" :
30- obj , err = get_key (obj , key )
68+ obj , err = get_key (obj , s . key )
3169 if err != nil {
3270 return nil , err
3371 }
3472 case "idx" :
3573 //fmt.Println("idx ----------------1")
36- obj , err = get_key (obj , key )
74+ obj , err = get_key (obj , s . key )
3775 if err != nil {
3876 return nil , err
3977 }
4078
41- if len (args .([]int )) > 1 {
79+ if len (s . args .([]int )) > 1 {
4280 //fmt.Println("idx ----------------2")
4381 res := []interface {}{}
44- for _ , x := range args .([]int ) {
82+ for _ , x := range s . args .([]int ) {
4583 //fmt.Println("idx ---- ", x)
4684 tmp , err := get_idx (obj , x )
4785 if err != nil {
@@ -50,9 +88,9 @@ func JsonPathLookup(obj interface{}, jpath string) (interface{}, error) {
5088 res = append (res , tmp )
5189 }
5290 obj = res
53- } else if len (args .([]int )) == 1 {
91+ } else if len (s . args .([]int )) == 1 {
5492 //fmt.Println("idx ----------------3")
55- obj , err = get_idx (obj , args .([]int )[0 ])
93+ obj , err = get_idx (obj , s . args .([]int )[0 ])
5694 if err != nil {
5795 return nil , err
5896 }
@@ -61,11 +99,11 @@ func JsonPathLookup(obj interface{}, jpath string) (interface{}, error) {
6199 return nil , fmt .Errorf ("cannot index on empty slice" )
62100 }
63101 case "range" :
64- obj , err = get_key (obj , key )
102+ obj , err = get_key (obj , s . key )
65103 if err != nil {
66104 return nil , err
67105 }
68- if argsv , ok := args .([2 ]interface {}); ok == true {
106+ if argsv , ok := s . args .([2 ]interface {}); ok == true {
69107 obj , err = get_range (obj , argsv [0 ], argsv [1 ])
70108 if err != nil {
71109 return nil , err
@@ -74,11 +112,11 @@ func JsonPathLookup(obj interface{}, jpath string) (interface{}, error) {
74112 return nil , fmt .Errorf ("range args length should be 2" )
75113 }
76114 case "filter" :
77- obj , err = get_key (obj , key )
115+ obj , err = get_key (obj , s . key )
78116 if err != nil {
79117 return nil , err
80118 }
81- obj , err = get_filtered (obj , obj , args .(string ))
119+ obj , err = get_filtered (obj , obj , s . args .(string ))
82120 if err != nil {
83121 return nil , err
84122 }
0 commit comments