Skip to content

Commit 28480c2

Browse files
committed
Optimize key check in get_key
1 parent 2d28d0b commit 28480c2

2 files changed

Lines changed: 51 additions & 22 deletions

File tree

jsonpath.go

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ import (
44
"fmt"
55
"github.com/mohae/utilitybelt/deepcopy"
66
//"golang.org/x/tools/go/types"
7+
"errors"
78
"go/token"
89
"go/types"
910
"reflect"
1011
"strconv"
1112
"strings"
12-
"errors"
1313
)
1414

1515
var ErrGetFromNullObj = errors.New("get attribute from null object")
@@ -283,6 +283,16 @@ func get_key(obj interface{}, key string) (interface{}, error) {
283283
}
284284
switch reflect.TypeOf(obj).Kind() {
285285
case reflect.Map:
286+
// if obj came from stdlib json, its highly likely to be a map[string]interface{}
287+
// in which case we can save having to iterate the map keys to work out if the
288+
// key exists
289+
if jsonMap, ok := obj.(map[string]interface{}); ok {
290+
val, exists := jsonMap[key]
291+
if !exists {
292+
return nil, fmt.Errorf("key error: %s not found in object", key)
293+
}
294+
return val, nil
295+
}
286296
for _, kv := range reflect.ValueOf(obj).MapKeys() {
287297
//fmt.Println(kv.String())
288298
if kv.String() == key {
@@ -417,9 +427,12 @@ func parse_filter(filter string) (lp string, op string, rp string, err error) {
417427
str_embrace = true
418428
} else {
419429
switch stage {
420-
case 0: lp = tmp
421-
case 1: op = tmp
422-
case 2: rp = tmp
430+
case 0:
431+
lp = tmp
432+
case 1:
433+
op = tmp
434+
case 2:
435+
rp = tmp
423436
}
424437
tmp = ""
425438
}
@@ -429,9 +442,12 @@ func parse_filter(filter string) (lp string, op string, rp string, err error) {
429442
continue
430443
}
431444
switch stage {
432-
case 0: lp = tmp
433-
case 1: op = tmp
434-
case 2: rp = tmp
445+
case 0:
446+
lp = tmp
447+
case 1:
448+
op = tmp
449+
case 2:
450+
rp = tmp
435451
}
436452
tmp = ""
437453

@@ -448,8 +464,10 @@ func parse_filter(filter string) (lp string, op string, rp string, err error) {
448464
case 0:
449465
lp = tmp
450466
op = "exists"
451-
case 1: op = tmp
452-
case 2: rp = tmp
467+
case 1:
468+
op = tmp
469+
case 2:
470+
rp = tmp
453471
}
454472
tmp = ""
455473
}
@@ -528,11 +546,11 @@ func eval_filter(obj, root interface{}, lp, op, rp string) (res bool, err error)
528546

529547
func isNumber(o interface{}) bool {
530548
switch v := o.(type) {
531-
case int,int8,int16,int32,int64:
549+
case int, int8, int16, int32, int64:
532550
return true
533-
case uint,uint8,uint16,uint32,uint64:
551+
case uint, uint8, uint16, uint32, uint64:
534552
return true
535-
case float32,float64:
553+
case float32, float64:
536554
return true
537555
case string:
538556
_, err := strconv.ParseFloat(v, 64)

jsonpath_test.go

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,18 @@ func init() {
5555
json.Unmarshal([]byte(data), &json_data)
5656
}
5757

58+
func Benchmark_JsonPathLookup(b *testing.B) {
59+
for n := 0; n < b.N; n++ {
60+
res, err := JsonPathLookup(json_data, "$.store.book[0].price")
61+
if res_v, ok := res.(float64); ok != true || res_v != 8.95 {
62+
b.Errorf("$.store.book[0].price should be 8.95")
63+
}
64+
if err != nil {
65+
b.Errorf("Unexpected error: %v", err)
66+
}
67+
}
68+
}
69+
5870
func Test_jsonpath_JsonPathLookup_1(t *testing.T) {
5971
// key from root
6072
res, _ := JsonPathLookup(json_data, "$.expensive")
@@ -850,24 +862,24 @@ var tcase_cmp_any = []map[string]interface{}{
850862
"op": "=~",
851863
"exp": false,
852864
"err": "op should only be <, <=, ==, >= and >",
853-
},{
865+
}, {
854866
"obj1": ifc1,
855867
"obj2": ifc1,
856868
"op": "==",
857869
"exp": true,
858-
"err": nil,
859-
},{
870+
"err": nil,
871+
}, {
860872
"obj1": ifc2,
861873
"obj2": ifc2,
862874
"op": "==",
863875
"exp": true,
864-
"err": nil,
865-
},{
876+
"err": nil,
877+
}, {
866878
"obj1": 20,
867879
"obj2": "100",
868-
"op": ">",
869-
"exp": false,
870-
"err": nil,
880+
"op": ">",
881+
"exp": false,
882+
"err": nil,
871883
},
872884
}
873885

@@ -935,7 +947,6 @@ func Test_jsonpath_string_equal(t *testing.T) {
935947
"expensive": 10
936948
}`
937949

938-
939950
var j interface{}
940951

941952
json.Unmarshal([]byte(data), &j)
@@ -982,4 +993,4 @@ func Test_jsonpath_num_cmp(t *testing.T) {
982993
t.Fatal("should return [], got: ", arr)
983994
}
984995

985-
}
996+
}

0 commit comments

Comments
 (0)