From 0df18d3bf8fa226f395490c6afe676dfa93396e0 Mon Sep 17 00:00:00 2001 From: Edward Yakop Date: Fri, 27 Jun 2025 06:50:39 +0800 Subject: [PATCH] Support for * nested struct with pointer to slice * filter of pointer to basic types --- jp/get.go | 4 ++++ jp/get_test.go | 20 ++++++++++++++++++++ jp/script.go | 12 ++++++++++++ 3 files changed, 36 insertions(+) diff --git a/jp/get.go b/jp/get.go index 779998b..040a8d6 100644 --- a/jp/get.go +++ b/jp/get.go @@ -1859,6 +1859,10 @@ func reflectGetNth(data any, i int) (v any, has bool) { if !isNil(data) { rd := reflect.ValueOf(data) rt := rd.Type() + if rt.Kind() == reflect.Ptr { + rt = rt.Elem() + rd = rd.Elem() + } switch rt.Kind() { case reflect.Slice, reflect.Array: size := rd.Len() diff --git a/jp/get_test.go b/jp/get_test.go index d3ac524..e1f1f65 100644 --- a/jp/get_test.go +++ b/jp/get_test.go @@ -26,6 +26,12 @@ type Sample struct { B string } +type NestedSample struct { + A *bool + B *string + C *[]NestedSample +} + type One struct { A int } @@ -211,6 +217,11 @@ var ( {path: "$[-10:]", expect: []any{1, 2, 3}, data: []int{1, 2, 3}}, {path: "$[1:-10:-1]", expect: []any{1, 2}, data: []int{1, 2, 3}}, {path: "$[2:10]", expect: []any{3}, data: []int{1, 2, 3}}, + { + path: "$.x[*].c[0].b", + expect: []any{ptr("1")}, + data: Any{X: []*NestedSample{{C: &[]NestedSample{{A: ptr(false), B: ptr("1")}, {A: ptr(true), B: ptr("2")}}}}}, + }, // filter with map { path: "$.x[?(@.b=='sample1')].a", @@ -243,6 +254,11 @@ var ( expect: []any{"sample2"}, data: Any{X: []*Sample{{A: 4, B: "sample2"}}}, }, + { + path: "$.x[*].c[?(@.a==true)].b", + expect: []any{ptr("2")}, + data: Any{X: []*NestedSample{{C: &[]NestedSample{{A: ptr(false), B: ptr("1")}, {A: ptr(true), B: ptr("2")}}}}}, + }, {path: "$.*", expect: []any{}, data: &one}, {path: "['a',-1]", expect: []any{3}, data: []any{1, 2, 3}}, {path: "['a','b']", expect: []any{}, data: []any{1, 2, 3}}, @@ -253,6 +269,10 @@ var ( } ) +func ptr[T any](v T) *T { + return &v +} + var ( firstData1 = map[string]any{"a": []any{map[string]any{"b": 2}}} one = &One{A: 3} diff --git a/jp/script.go b/jp/script.go index 8cf00fc..c1c67a6 100644 --- a/jp/script.go +++ b/jp/script.go @@ -229,6 +229,9 @@ func (s *Script) evalWithRoot(stack, data, root any) (any, Expr) { data = da default: rv := reflect.ValueOf(td) + if rt := rv.Type(); rt.Kind() == reflect.Ptr { + rv = rv.Elem() + } if rv.Kind() != reflect.Slice && rv.Kind() != reflect.Array { return stack, locs } @@ -373,6 +376,7 @@ func (s *Script) evalWithRoot(stack, data, root any) (any, Expr) { } func normalize(v any) any { +Start: switch tv := v.(type) { case int: v = int64(tv) @@ -402,6 +406,14 @@ func normalize(v any) any { v = int64(tv) case gen.Float: v = float64(tv) + default: + if rt := reflect.TypeOf(v); rt != nil && rt.Kind() == reflect.Ptr { + rv := reflect.ValueOf(v) + if !rv.IsNil() { + v = rv.Elem().Interface() + goto Start + } + } } return v }