diff --git a/README.md b/README.md index 532c96d..710ab36 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ you use, `jmespath.Search`: > import "github.com/jmespath-community/go-jmespath" > > var jsondata = []byte(`{"foo": {"bar": {"baz": [0, 1, 2, 3, 4]}}}`) // your data -> var data interface{} +> var data any > err := json.Unmarshal(jsondata, &data) > result, err := jmespath.Search("foo.bar.baz[2]", data) result = 2 @@ -34,7 +34,7 @@ from a list. Here are a few more examples: ```go > var jsondata = []byte(`{"foo": {"bar": {"baz": [0, 1, 2, 3, 4]}}}`) // your data -> var data interface{} +> var data any > err := json.Unmarshal(jsondata, &data) > result, err := jmespath.Search("foo.bar", data) result = { "baz": [ 0, 1, 2, 3, 4 ] } @@ -42,7 +42,7 @@ result = { "baz": [ 0, 1, 2, 3, 4 ] } > var jsondata = []byte(`{"foo": [{"first": "a", "last": "b"}, {"first": "c", "last": "d"}]}`) // your data -> var data interface{} +> var data any > err := json.Unmarshal(jsondata, &data) > result, err := jmespath.Search({"foo[*].first", data) result [ 'a', 'c' ] @@ -51,7 +51,7 @@ result [ 'a', 'c' ] > var jsondata = []byte(`{"foo": [{"age": 20}, {"age": 25}, {"age": 30}, {"age": 35}, {"age": 40}]}`) // your data -> var data interface{} +> var data any > err := json.Unmarshal(jsondata, &data) > result, err := jmespath.Search("foo[?age > `30`]") result = [ { age: 35 }, { age: 40 } ] @@ -62,7 +62,7 @@ you are going to run multiple searches with it: ```go > var jsondata = []byte(`{"foo": "bar"}`) -> var data interface{} +> var data any > err := json.Unmarshal(jsondata, &data) > precompiled, err := Compile("foo") > if err != nil{ diff --git a/cmd/jpgo/main.go b/cmd/jpgo/main.go index 112a0b4..e9a62ec 100644 --- a/cmd/jpgo/main.go +++ b/cmd/jpgo/main.go @@ -80,7 +80,7 @@ func (c command) run(cmd *cobra.Command, args []string) error { return fmt.Errorf("error reading from stdin: %w", err) } } - var data interface{} + var data any if err := json.Unmarshal(inputData, &data); err != nil { return fmt.Errorf("invalid input JSON: %w", err) } diff --git a/jp_test.go b/jp_test.go index cffd2f5..f1e3ae8 100644 --- a/jp_test.go +++ b/jp_test.go @@ -13,7 +13,7 @@ import ( ) type TestSuite struct { - Given interface{} + Given any TestCases []TestCase `json:"cases"` Comment string } @@ -21,7 +21,7 @@ type TestSuite struct { type TestCase struct { Comment string Expression string - Result interface{} + Result any Error string } @@ -80,7 +80,7 @@ func runTestSuite(assert *assert.Assertions, testsuite TestSuite, filename strin } } -func runSyntaxTestCase(assert *assert.Assertions, given interface{}, testcase TestCase, filename string) { +func runSyntaxTestCase(assert *assert.Assertions, given any, testcase TestCase, filename string) { // Anything with an .Error means that we expect that JMESPath should return // an error when we try to evaluate the expression. // fmt.Println(fmt.Sprintf("%s: %s", filename, testcase.Expression)) @@ -88,7 +88,7 @@ func runSyntaxTestCase(assert *assert.Assertions, given interface{}, testcase Te assert.NotNil(err, fmt.Sprintf("Expression: %s", testcase.Expression)) } -func runTestCase(assert *assert.Assertions, given interface{}, testcase TestCase, filename string) { +func runTestCase(assert *assert.Assertions, given any, testcase TestCase, filename string) { lexer := parsing.NewLexer() var err error _, err = lexer.Tokenize(testcase.Expression) diff --git a/pkg/api/api.go b/pkg/api/api.go index 1050bf6..9d784dd 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -10,7 +10,7 @@ import ( // JMESPath is the representation of a compiled JMES path query. A JMESPath is // safe for concurrent use by multiple goroutines. type JMESPath interface { - Search(interface{}, ...interpreter.Option) (interface{}, error) + Search(any, ...interpreter.Option) (any, error) } type jmesPath struct { @@ -46,13 +46,13 @@ func MustCompile(expression string) JMESPath { } // Search evaluates a JMESPath expression against input data and returns the result. -func (jp jmesPath) Search(data interface{}, opts ...interpreter.Option) (interface{}, error) { +func (jp jmesPath) Search(data any, opts ...interpreter.Option) (any, error) { intr := interpreter.NewInterpreter(data, nil) return intr.Execute(jp.node, data, opts...) } // Search evaluates a JMESPath expression against input data and returns the result. -func Search(expression string, data interface{}, opts ...interpreter.Option) (interface{}, error) { +func Search(expression string, data any, opts ...interpreter.Option) (any, error) { compiled, err := Compile(expression) if err != nil { return nil, err diff --git a/pkg/api/api_test.go b/pkg/api/api_test.go index e85eb31..83c1c49 100644 --- a/pkg/api/api_test.go +++ b/pkg/api/api_test.go @@ -12,7 +12,7 @@ import ( func TestValidUncompiledExpressionSearches(t *testing.T) { assert := assert.New(t) j := []byte(`{"foo": {"bar": {"baz": [0, 1, 2, 3, 4]}}}`) - var d interface{} + var d any err := json.Unmarshal(j, &d) assert.Nil(err) result, err := Search("foo.bar.baz[2]", d) @@ -22,7 +22,7 @@ func TestValidUncompiledExpressionSearches(t *testing.T) { func TestValidPrecompiledExpressionSearches(t *testing.T) { assert := assert.New(t) - data := make(map[string]interface{}) + data := make(map[string]any) data["foo"] = "bar" precompiled, err := Compile("foo") assert.Nil(err) @@ -45,7 +45,7 @@ func TestInvalidMustCompilePanics(t *testing.T) { MustCompile("not a valid expression") } -func jpfEcho(arguments []interface{}) (interface{}, error) { +func jpfEcho(arguments []any) (any, error) { return arguments[0], nil } @@ -54,13 +54,13 @@ func TestSearch(t *testing.T) { type args struct { expression string - data interface{} + data any funcs []functions.FunctionEntry } tests := []struct { name string args args - want interface{} + want any wantErr bool }{{ args: args{ @@ -70,13 +70,13 @@ func TestSearch(t *testing.T) { }, { args: args{ expression: "sort_by(@, &@ *`-1.0`)", - data: []interface{}{1.0, 2.0, 3.0, 4.0, 5.0}, + data: []any{1.0, 2.0, 3.0, 4.0, 5.0}, }, - want: []interface{}{5.0, 4.0, 3.0, 2.0, 1.0}, + want: []any{5.0, 4.0, 3.0, 2.0, 1.0}, }, { args: args{ expression: "echo(@)", - data: []interface{}{1.0, 2.0, 3.0, 4.0, 5.0}, + data: []any{1.0, 2.0, 3.0, 4.0, 5.0}, funcs: []functions.FunctionEntry{{ Name: "echo", Handler: jpfEcho, @@ -85,7 +85,7 @@ func TestSearch(t *testing.T) { }, }}, }, - want: []interface{}{1.0, 2.0, 3.0, 4.0, 5.0}, + want: []any{1.0, 2.0, 3.0, 4.0, 5.0}, }, { args: args{ expression: "echo(@)", @@ -121,7 +121,7 @@ func TestSearch(t *testing.T) { }, { args: args{ expression: `@."$".a`, - data: map[string]interface{}{ + data: map[string]any{ "a": 42.0, }, }, @@ -130,13 +130,13 @@ func TestSearch(t *testing.T) { args: args{ expression: "`null` | {foo: @}", }, - want: map[string]interface{}{ + want: map[string]any{ "foo": nil, }, }, { args: args{ expression: "let $root = @ in $root.a", - data: map[string]interface{}{ + data: map[string]any{ "a": 42.0, }, }, @@ -144,7 +144,7 @@ func TestSearch(t *testing.T) { }, { args: args{ expression: "contains(@, { foo: 'bar' })", - data: []interface{}{map[string]any{}, nil, map[string]any{"foo": "bar"}}, + data: []any{map[string]any{}, nil, map[string]any{"foo": "bar"}}, }, want: true, }, { diff --git a/pkg/binding/binding.go b/pkg/binding/binding.go index d88ef56..e181032 100644 --- a/pkg/binding/binding.go +++ b/pkg/binding/binding.go @@ -4,18 +4,18 @@ package binding // You can get the value of the binding by calling the `Value` method. type Binding interface { // Get returns the value bound for a given name. - Value() (interface{}, error) + Value() (any, error) } type binding struct { - value interface{} + value any } -func (b *binding) Value() (interface{}, error) { +func (b *binding) Value() (any, error) { return b.value, nil } -func NewBinding(value interface{}) Binding { +func NewBinding(value any) Binding { return &binding{ value: value, } diff --git a/pkg/binding/binding_test.go b/pkg/binding/binding_test.go index 1f21591..e3c7512 100644 --- a/pkg/binding/binding_test.go +++ b/pkg/binding/binding_test.go @@ -8,7 +8,7 @@ import ( func TestNewBinding(t *testing.T) { tests := []struct { name string - value interface{} + value any want Binding }{{ name: "nil", @@ -24,8 +24,8 @@ func TestNewBinding(t *testing.T) { want: &binding{"42"}, }, { name: "array", - value: []interface{}{"42", 42}, - want: &binding{[]interface{}{"42", 42}}, + value: []any{"42", 42}, + want: &binding{[]any{"42", 42}}, }} for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -39,8 +39,8 @@ func TestNewBinding(t *testing.T) { func Test_binding_Value(t *testing.T) { tests := []struct { name string - value interface{} - want interface{} + value any + want any wantErr bool }{{ name: "nil", @@ -59,8 +59,8 @@ func Test_binding_Value(t *testing.T) { wantErr: false, }, { name: "array", - value: []interface{}{"42", 42}, - want: []interface{}{"42", 42}, + value: []any{"42", 42}, + want: []any{"42", 42}, wantErr: false, }} for _, tt := range tests { diff --git a/pkg/binding/resolve.go b/pkg/binding/resolve.go index 80a718b..29c9eb1 100644 --- a/pkg/binding/resolve.go +++ b/pkg/binding/resolve.go @@ -4,7 +4,7 @@ import ( "errors" ) -func Resolve(name string, bindings Bindings) (interface{}, error) { +func Resolve(name string, bindings Bindings) (any, error) { if bindings == nil { return nil, errors.New("bindings must not be nil") } diff --git a/pkg/binding/resolve_test.go b/pkg/binding/resolve_test.go index 46ac7a3..a20933d 100644 --- a/pkg/binding/resolve_test.go +++ b/pkg/binding/resolve_test.go @@ -13,7 +13,7 @@ func TestResolve(t *testing.T) { tests := []struct { name string args args - want interface{} + want any wantErr bool }{{ name: "nil", diff --git a/pkg/functions/functions.go b/pkg/functions/functions.go index 94424a5..b656cc7 100644 --- a/pkg/functions/functions.go +++ b/pkg/functions/functions.go @@ -17,8 +17,8 @@ import ( ) type ( - JpFunction = func([]interface{}) (interface{}, error) - ExpRef = func(interface{}) (interface{}, error) + JpFunction = func([]any) (any, error) + ExpRef = func(any) (any, error) JpType string ) @@ -48,8 +48,8 @@ type ArgSpec struct { } type byExprString struct { - items []interface{} - keys []interface{} + items []any + keys []any hasError bool } @@ -77,8 +77,8 @@ func (a *byExprString) Less(i, j int) bool { } type byExprFloat struct { - items []interface{} - keys []interface{} + items []any + keys []any hasError bool } @@ -105,15 +105,15 @@ func (a *byExprFloat) Less(i, j int) bool { return ith < jth } -func jpfAbs(arguments []interface{}) (interface{}, error) { +func jpfAbs(arguments []any) (any, error) { num := arguments[0].(float64) return math.Abs(num), nil } -func jpfAvg(arguments []interface{}) (interface{}, error) { +func jpfAvg(arguments []any) (any, error) { // We've already type checked the value so we can safely use // type assertions. - args := arguments[0].([]interface{}) + args := arguments[0].([]any) length := float64(len(args)) if len(args) == 0 { return nil, nil @@ -125,12 +125,12 @@ func jpfAvg(arguments []interface{}) (interface{}, error) { return numerator / length, nil } -func jpfCeil(arguments []interface{}) (interface{}, error) { +func jpfCeil(arguments []any) (any, error) { val := arguments[0].(float64) return math.Ceil(val), nil } -func jpfContains(arguments []interface{}) (interface{}, error) { +func jpfContains(arguments []any) (any, error) { search := arguments[0] el := arguments[1] if searchStr, ok := search.(string); ok { @@ -139,8 +139,8 @@ func jpfContains(arguments []interface{}) (interface{}, error) { } return false, nil } - // Otherwise this is a generic contains for []interface{} - general := search.([]interface{}) + // Otherwise this is a generic contains for []any + general := search.([]any) for _, item := range general { if reflect.DeepEqual(el, item) { return true, nil @@ -149,13 +149,13 @@ func jpfContains(arguments []interface{}) (interface{}, error) { return false, nil } -func jpfEndsWith(arguments []interface{}) (interface{}, error) { +func jpfEndsWith(arguments []any) (any, error) { search := arguments[0].(string) suffix := arguments[1].(string) return strings.HasSuffix(search, suffix), nil } -func jpfFindImpl(name string, arguments []interface{}, find func(s string, substr string) int) (interface{}, error) { +func jpfFindImpl(name string, arguments []any, find func(s string, substr string) int) (any, error) { subject := arguments[0].(string) substr := arguments[1].(string) @@ -191,22 +191,22 @@ func jpfFindImpl(name string, arguments []interface{}, find func(s string, subst return float64(start + offset), nil } -func jpfFindFirst(arguments []interface{}) (interface{}, error) { +func jpfFindFirst(arguments []any) (any, error) { return jpfFindImpl("find_first", arguments, strings.Index) } -func jpfFindLast(arguments []interface{}) (interface{}, error) { +func jpfFindLast(arguments []any) (any, error) { return jpfFindImpl("find_last", arguments, strings.LastIndex) } -func jpfFloor(arguments []interface{}) (interface{}, error) { +func jpfFloor(arguments []any) (any, error) { val := arguments[0].(float64) return math.Floor(val), nil } -func jpfFromItems(arguments []interface{}) (interface{}, error) { +func jpfFromItems(arguments []any) (any, error) { if arr, ok := util.ToArrayArray(arguments[0]); ok { - result := make(map[string]interface{}) + result := make(map[string]any) for _, item := range arr { if len(item) != 2 { return nil, errors.New("invalid value, each array must contain two elements, a pair of string and value") @@ -223,13 +223,13 @@ func jpfFromItems(arguments []interface{}) (interface{}, error) { return nil, errors.New("invalid type, first argument must be an array of arrays") } -func jpfGroupBy(arguments []interface{}) (interface{}, error) { - arr := arguments[0].([]interface{}) +func jpfGroupBy(arguments []any) (any, error) { + arr := arguments[0].([]any) exp := arguments[1].(ExpRef) if len(arr) == 0 { return nil, nil } - groups := map[string]interface{}{} + groups := map[string]any{} for _, element := range arr { spec, err := exp(element) if err != nil { @@ -240,65 +240,65 @@ func jpfGroupBy(arguments []interface{}) (interface{}, error) { return nil, errors.New("invalid type, the expression must evaluate to a string") } if _, ok := groups[key]; !ok { - groups[key] = []interface{}{} + groups[key] = []any{} } - groups[key] = append(groups[key].([]interface{}), element) + groups[key] = append(groups[key].([]any), element) } return groups, nil } -func jpfItems(arguments []interface{}) (interface{}, error) { - value := arguments[0].(map[string]interface{}) - arrays := []interface{}{} +func jpfItems(arguments []any) (any, error) { + value := arguments[0].(map[string]any) + arrays := []any{} for key, item := range value { - var element interface{} = []interface{}{key, item} + var element any = []any{key, item} arrays = append(arrays, element) } return arrays, nil } -func jpfJoin(arguments []interface{}) (interface{}, error) { +func jpfJoin(arguments []any) (any, error) { sep := arguments[0].(string) // We can't just do arguments[1].([]string), we have to // manually convert each item to a string. arrayStr := []string{} - for _, item := range arguments[1].([]interface{}) { + for _, item := range arguments[1].([]any) { arrayStr = append(arrayStr, item.(string)) } return strings.Join(arrayStr, sep), nil } -func jpfKeys(arguments []interface{}) (interface{}, error) { - arg := arguments[0].(map[string]interface{}) - collected := make([]interface{}, 0, len(arg)) +func jpfKeys(arguments []any) (any, error) { + arg := arguments[0].(map[string]any) + collected := make([]any, 0, len(arg)) for key := range arg { collected = append(collected, key) } return collected, nil } -func jpfLength(arguments []interface{}) (interface{}, error) { +func jpfLength(arguments []any) (any, error) { arg := arguments[0] if c, ok := arg.(string); ok { return float64(utf8.RuneCountInString(c)), nil } else if util.IsSliceType(arg) { v := reflect.ValueOf(arg) return float64(v.Len()), nil - } else if c, ok := arg.(map[string]interface{}); ok { + } else if c, ok := arg.(map[string]any); ok { return float64(len(c)), nil } return nil, errors.New("could not compute length()") } -func jpfLower(arguments []interface{}) (interface{}, error) { +func jpfLower(arguments []any) (any, error) { return strings.ToLower(arguments[0].(string)), nil } -func jpfMap(arguments []interface{}) (interface{}, error) { +func jpfMap(arguments []any) (any, error) { exp := arguments[0].(ExpRef) - arr := arguments[1].([]interface{}) - mapped := make([]interface{}, 0, len(arr)) + arr := arguments[1].([]any) + mapped := make([]any, 0, len(arr)) for _, value := range arr { current, err := exp(value) if err != nil { @@ -309,7 +309,7 @@ func jpfMap(arguments []interface{}) (interface{}, error) { return mapped, nil } -func jpfMax(arguments []interface{}) (interface{}, error) { +func jpfMax(arguments []any) (any, error) { if items, ok := util.ToArrayNum(arguments[0]); ok { if len(items) == 0 { return nil, nil @@ -342,8 +342,8 @@ func jpfMax(arguments []interface{}) (interface{}, error) { return best, nil } -func jpfMaxBy(arguments []interface{}) (interface{}, error) { - arr := arguments[0].([]interface{}) +func jpfMaxBy(arguments []any) (any, error) { + arr := arguments[0].([]any) exp := arguments[1].(ExpRef) if len(arr) == 0 { return nil, nil @@ -396,10 +396,10 @@ func jpfMaxBy(arguments []interface{}) (interface{}, error) { } } -func jpfMerge(arguments []interface{}) (interface{}, error) { - final := make(map[string]interface{}) +func jpfMerge(arguments []any) (any, error) { + final := make(map[string]any) for _, m := range arguments { - mapped := m.(map[string]interface{}) + mapped := m.(map[string]any) for key, value := range mapped { final[key] = value } @@ -407,7 +407,7 @@ func jpfMerge(arguments []interface{}) (interface{}, error) { return final, nil } -func jpfMin(arguments []interface{}) (interface{}, error) { +func jpfMin(arguments []any) (any, error) { if items, ok := util.ToArrayNum(arguments[0]); ok { if len(items) == 0 { return nil, nil @@ -439,8 +439,8 @@ func jpfMin(arguments []interface{}) (interface{}, error) { return best, nil } -func jpfMinBy(arguments []interface{}) (interface{}, error) { - arr := arguments[0].([]interface{}) +func jpfMinBy(arguments []any) (any, error) { + arr := arguments[0].([]any) exp := arguments[1].(ExpRef) if len(arr) == 0 { return nil, nil @@ -492,7 +492,7 @@ func jpfMinBy(arguments []interface{}) (interface{}, error) { } } -func jpfNotNull(arguments []interface{}) (interface{}, error) { +func jpfNotNull(arguments []any) (any, error) { for _, arg := range arguments { if arg != nil { return arg, nil @@ -503,9 +503,9 @@ func jpfNotNull(arguments []interface{}) (interface{}, error) { func jpfPadImpl( name string, - arguments []interface{}, + arguments []any, pad func(s string, width int, pad string) string, -) (interface{}, error) { +) (any, error) { s := arguments[0].(string) width, ok := util.ToPositiveInteger(arguments[1]) if !ok { @@ -522,11 +522,11 @@ func jpfPadImpl( return pad(s, width, chars), nil } -func jpfPadLeft(arguments []interface{}) (interface{}, error) { +func jpfPadLeft(arguments []any) (any, error) { return jpfPadImpl("pad_left", arguments, padLeft) } -func jpfPadRight(arguments []interface{}) (interface{}, error) { +func jpfPadRight(arguments []any) (any, error) { return jpfPadImpl("pad_right", arguments, padRight) } @@ -544,7 +544,7 @@ func padRight(s string, width int, pad string) string { return result } -func jpfReplace(arguments []interface{}) (interface{}, error) { +func jpfReplace(arguments []any) (any, error) { subject := arguments[0].(string) old := arguments[1].(string) new := arguments[2].(string) @@ -560,7 +560,7 @@ func jpfReplace(arguments []interface{}) (interface{}, error) { return strings.Replace(subject, old, new, count), nil } -func jpfReverse(arguments []interface{}) (interface{}, error) { +func jpfReverse(arguments []any) (any, error) { if s, ok := arguments[0].(string); ok { r := []rune(s) for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 { @@ -568,20 +568,20 @@ func jpfReverse(arguments []interface{}) (interface{}, error) { } return string(r), nil } - items := arguments[0].([]interface{}) + items := arguments[0].([]any) length := len(items) - reversed := make([]interface{}, length) + reversed := make([]any, length) for i, item := range items { reversed[length-(i+1)] = item } return reversed, nil } -func jpfSort(arguments []interface{}) (interface{}, error) { +func jpfSort(arguments []any) (any, error) { if items, ok := util.ToArrayNum(arguments[0]); ok { d := sort.Float64Slice(items) sort.Stable(d) - final := make([]interface{}, len(d)) + final := make([]any, len(d)) for i, val := range d { final[i] = val } @@ -591,22 +591,22 @@ func jpfSort(arguments []interface{}) (interface{}, error) { items, _ := util.ToArrayStr(arguments[0]) d := sort.StringSlice(items) sort.Stable(d) - final := make([]interface{}, len(d)) + final := make([]any, len(d)) for i, val := range d { final[i] = val } return final, nil } -func jpfSortBy(arguments []interface{}) (interface{}, error) { - arr := arguments[0].([]interface{}) +func jpfSortBy(arguments []any) (any, error) { + arr := arguments[0].([]any) exp := arguments[1].(ExpRef) if len(arr) == 0 { return arr, nil } else if len(arr) == 1 { return arr, nil } - var sortKeys []interface{} + var sortKeys []any for _, item := range arr { if value, err := exp(item); err != nil { return nil, err @@ -633,10 +633,10 @@ func jpfSortBy(arguments []interface{}) (interface{}, error) { } } -func jpfSplit(arguments []interface{}) (interface{}, error) { +func jpfSplit(arguments []any) (any, error) { s := arguments[0].(string) if len(s) == 0 { - return []interface{}{}, nil + return []any{}, nil } sep := arguments[1].(string) @@ -651,7 +651,7 @@ func jpfSplit(arguments []interface{}) (interface{}, error) { } if nSpecified && n == 0 { - result := []interface{}{s} + result := []any{s} return result, nil } @@ -661,22 +661,22 @@ func jpfSplit(arguments []interface{}) (interface{}, error) { } splits := strings.SplitN(s, sep, count) - // convert []string to []interface{} ☹️ + // convert []string to []any ☹️ - result := []interface{}{} + result := []any{} for _, split := range splits { result = append(result, split) } return result, nil } -func jpfStartsWith(arguments []interface{}) (interface{}, error) { +func jpfStartsWith(arguments []any) (any, error) { search := arguments[0].(string) prefix := arguments[1].(string) return strings.HasPrefix(search, prefix), nil } -func jpfSum(arguments []interface{}) (interface{}, error) { +func jpfSum(arguments []any) (any, error) { items, _ := util.ToArrayNum(arguments[0]) sum := 0.0 for _, item := range items { @@ -685,14 +685,14 @@ func jpfSum(arguments []interface{}) (interface{}, error) { return sum, nil } -func jpfToArray(arguments []interface{}) (interface{}, error) { - if _, ok := arguments[0].([]interface{}); ok { +func jpfToArray(arguments []any) (any, error) { + if _, ok := arguments[0].([]any); ok { return arguments[0], nil } return arguments[:1:1], nil } -func jpfToString(arguments []interface{}) (interface{}, error) { +func jpfToString(arguments []any) (any, error) { if v, ok := arguments[0].(string); ok { return v, nil } @@ -703,7 +703,7 @@ func jpfToString(arguments []interface{}) (interface{}, error) { return string(result), nil } -func jpfToNumber(arguments []interface{}) (interface{}, error) { +func jpfToNumber(arguments []any) (any, error) { arg := arguments[0] if arg == nil { return nil, nil @@ -721,20 +721,20 @@ func jpfToNumber(arguments []interface{}) (interface{}, error) { } return conv, nil } - if _, ok := arg.([]interface{}); ok { + if _, ok := arg.([]any); ok { return nil, nil } - if _, ok := arg.(map[string]interface{}); ok { + if _, ok := arg.(map[string]any); ok { return nil, nil } return nil, errors.New("unknown type") } func jpfTrimImpl( - arguments []interface{}, + arguments []any, trimSpace func(s string, predicate func(r rune) bool) string, trim func(s string, cutset string) string, -) (interface{}, error) { +) (any, error) { s := arguments[0].(string) cutset := "" if len(arguments) > 1 { @@ -747,19 +747,19 @@ func jpfTrimImpl( return trim(s, cutset), nil } -func jpfTrim(arguments []interface{}) (interface{}, error) { +func jpfTrim(arguments []any) (any, error) { return jpfTrimImpl(arguments, strings.TrimFunc, strings.Trim) } -func jpfTrimLeft(arguments []interface{}) (interface{}, error) { +func jpfTrimLeft(arguments []any) (any, error) { return jpfTrimImpl(arguments, strings.TrimLeftFunc, strings.TrimLeft) } -func jpfTrimRight(arguments []interface{}) (interface{}, error) { +func jpfTrimRight(arguments []any) (any, error) { return jpfTrimImpl(arguments, strings.TrimRightFunc, strings.TrimRight) } -func jpfType(arguments []interface{}) (interface{}, error) { +func jpfType(arguments []any) (any, error) { arg := arguments[0] if _, ok := arg.(float64); ok { return "number", nil @@ -767,10 +767,10 @@ func jpfType(arguments []interface{}) (interface{}, error) { if _, ok := arg.(string); ok { return "string", nil } - if _, ok := arg.([]interface{}); ok { + if _, ok := arg.([]any); ok { return "array", nil } - if _, ok := arg.(map[string]interface{}); ok { + if _, ok := arg.(map[string]any); ok { return "object", nil } if arg == nil { @@ -782,39 +782,39 @@ func jpfType(arguments []interface{}) (interface{}, error) { return nil, errors.New("unknown type") } -func jpfUpper(arguments []interface{}) (interface{}, error) { +func jpfUpper(arguments []any) (any, error) { return strings.ToUpper(arguments[0].(string)), nil } -func jpfValues(arguments []interface{}) (interface{}, error) { - arg := arguments[0].(map[string]interface{}) - collected := make([]interface{}, 0, len(arg)) +func jpfValues(arguments []any) (any, error) { + arg := arguments[0].(map[string]any) + collected := make([]any, 0, len(arg)) for _, value := range arg { collected = append(collected, value) } return collected, nil } -func jpfZip(arguments []interface{}) (interface{}, error) { +func jpfZip(arguments []any) (any, error) { // determine how many items are present // for each array in the result count := math.MaxInt for _, item := range arguments { - arr := item.([]interface{}) + arr := item.([]any) // TODO: use go1.18 min[T constraints.Ordered] generic function count = int(math.Min(float64(count), float64(len(arr)))) } - result := []interface{}{} + result := []any{} for i := 0; i < count; i++ { - nth := []interface{}{} + nth := []any{} for _, item := range arguments { - arr := item.([]interface{}) + arr := item.([]any) nth = append(nth, arr[i]) } - result = append(result, interface{}(nth)) + result = append(result, any(nth)) } return result, nil diff --git a/pkg/interpreter/functions.go b/pkg/interpreter/functions.go index 6e32ff6..6cf2afe 100644 --- a/pkg/interpreter/functions.go +++ b/pkg/interpreter/functions.go @@ -10,7 +10,7 @@ import ( ) type FunctionCaller interface { - CallFunction(string, []interface{}) (interface{}, error) + CallFunction(string, []any) (any, error) } type functionEntry struct { @@ -35,7 +35,7 @@ func NewFunctionCaller(funcs ...functions.FunctionEntry) *functionCaller { } } -func resolveArgs(name string, function functionEntry, arguments []interface{}) ([]interface{}, error) { +func resolveArgs(name string, function functionEntry, arguments []any) ([]any, error) { if len(function.arguments) == 0 { return arguments, nil } @@ -102,7 +102,7 @@ func getMaxExpected(arguments []functions.ArgSpec) (int, bool) { return len(arguments), true } -func typeCheck(a functions.ArgSpec, arg interface{}) error { +func typeCheck(a functions.ArgSpec, arg any) error { for _, t := range a.Types { switch t { case functions.JpNumber: @@ -118,12 +118,12 @@ func typeCheck(a functions.ArgSpec, arg interface{}) error { return nil } case functions.JpObject: - if _, ok := arg.(map[string]interface{}); ok { + if _, ok := arg.(map[string]any); ok { return nil } case functions.JpArrayArray: if util.IsSliceType(arg) { - if _, ok := arg.([]interface{}); ok { + if _, ok := arg.([]any); ok { return nil } } @@ -146,7 +146,7 @@ func typeCheck(a functions.ArgSpec, arg interface{}) error { return fmt.Errorf("invalid type for: %v, expected: %#v", arg, a.Types) } -func (f *functionCaller) CallFunction(name string, arguments []interface{}) (interface{}, error) { +func (f *functionCaller) CallFunction(name string, arguments []any) (any, error) { entry, ok := f.functionTable[name] if !ok { return nil, errors.New("unknown function: " + name) diff --git a/pkg/interpreter/interpreter.go b/pkg/interpreter/interpreter.go index 33f6311..5f15aa0 100644 --- a/pkg/interpreter/interpreter.go +++ b/pkg/interpreter/interpreter.go @@ -21,15 +21,15 @@ This is a tree based interpreter. It walks the AST and directly interprets the AST to search through a JSON document. */ type Interpreter interface { - Execute(parsing.ASTNode, interface{}, ...Option) (interface{}, error) + Execute(parsing.ASTNode, any, ...Option) (any, error) } type treeInterpreter struct { - root interface{} + root any bindings binding.Bindings } -func NewInterpreter(data interface{}, bindings binding.Bindings) Interpreter { +func NewInterpreter(data any, bindings binding.Bindings) Interpreter { if bindings == nil { bindings = binding.NewBindings() } @@ -42,7 +42,7 @@ func NewInterpreter(data interface{}, bindings binding.Bindings) Interpreter { // Execute takes an ASTNode and input data and interprets the AST directly. // It will produce the result of applying the JMESPath expression associated // with the ASTNode to the input data "value". -func (intr *treeInterpreter) Execute(node parsing.ASTNode, value interface{}, opts ...Option) (interface{}, error) { +func (intr *treeInterpreter) Execute(node parsing.ASTNode, value any, opts ...Option) (any, error) { var o Options for _, opt := range opts { if opt != nil { @@ -56,7 +56,7 @@ func (intr *treeInterpreter) Execute(node parsing.ASTNode, value interface{}, op return intr.execute(node, value, functionCaller) } -func (intr *treeInterpreter) execute(node parsing.ASTNode, value interface{}, functionCaller FunctionCaller) (interface{}, error) { +func (intr *treeInterpreter) execute(node parsing.ASTNode, value any, functionCaller FunctionCaller) (any, error) { switch node.NodeType { case parsing.ASTArithmeticUnaryExpression: expr, err := intr.execute(node.Children[0], value, functionCaller) @@ -140,11 +140,11 @@ func (intr *treeInterpreter) execute(node parsing.ASTNode, value interface{}, fu return leftNum <= rightNum, nil } case parsing.ASTExpRef: - return func(data interface{}) (interface{}, error) { + return func(data any) (any, error) { return intr.execute(node.Children[0], data, functionCaller) }, nil case parsing.ASTFunctionExpression: - resolvedArgs := []interface{}{} + resolvedArgs := []any{} for _, arg := range node.Children { current, err := intr.execute(arg, value, functionCaller) if err != nil { @@ -160,7 +160,7 @@ func (intr *treeInterpreter) execute(node parsing.ASTNode, value interface{}, fu if err != nil { return nil, nil } - sliceType, ok := left.([]interface{}) + sliceType, ok := left.([]any) if !ok { if util.IsSliceType(left) { return intr.filterProjectionWithReflection(node, left, functionCaller) @@ -168,7 +168,7 @@ func (intr *treeInterpreter) execute(node parsing.ASTNode, value interface{}, fu return nil, nil } compareNode := node.Children[2] - collected := []interface{}{} + collected := []any{} for _, element := range sliceType { result, err := intr.execute(compareNode, element, functionCaller) if err != nil { @@ -190,9 +190,9 @@ func (intr *treeInterpreter) execute(node parsing.ASTNode, value interface{}, fu if err != nil { return nil, nil } - sliceType, ok := left.([]interface{}) + sliceType, ok := left.([]any) if !ok { - // If we can't type convert to []interface{}, there's + // If we can't type convert to []any, there's // a chance this could still work via reflection if we're // dealing with user provided types. if util.IsSliceType(left) { @@ -200,12 +200,12 @@ func (intr *treeInterpreter) execute(node parsing.ASTNode, value interface{}, fu } return nil, nil } - flattened := []interface{}{} + flattened := []any{} for _, element := range sliceType { - if elementSlice, ok := element.([]interface{}); ok { + if elementSlice, ok := element.([]any); ok { flattened = append(flattened, elementSlice...) } else if util.IsSliceType(element) { - reflectFlat := []interface{}{} + reflectFlat := []any{} v := reflect.ValueOf(element) for i := 0; i < v.Len(); i++ { reflectFlat = append(reflectFlat, v.Index(i).Interface()) @@ -254,7 +254,7 @@ func (intr *treeInterpreter) execute(node parsing.ASTNode, value interface{}, fu return value, nil } case parsing.ASTIndex: - if sliceType, ok := value.([]interface{}); ok { + if sliceType, ok := value.([]any); ok { index := node.Value.(int) if index < 0 { index += len(sliceType) @@ -282,7 +282,7 @@ func (intr *treeInterpreter) execute(node parsing.ASTNode, value interface{}, fu case parsing.ASTLiteral: return node.Value, nil case parsing.ASTMultiSelectHash: - collected := make(map[string]interface{}) + collected := make(map[string]any) for _, child := range node.Children { current, err := intr.execute(child, value, functionCaller) if err != nil { @@ -293,7 +293,7 @@ func (intr *treeInterpreter) execute(node parsing.ASTNode, value interface{}, fu } return collected, nil case parsing.ASTMultiSelectList: - collected := []interface{}{} + collected := []any{} for _, child := range node.Children { current, err := intr.execute(child, value, functionCaller) if err != nil { @@ -367,7 +367,7 @@ func (intr *treeInterpreter) execute(node parsing.ASTNode, value interface{}, fu return nil, err } - sliceType, ok := left.([]interface{}) + sliceType, ok := left.([]any) if !ok { if util.IsSliceType(left) { return intr.projectWithReflection(node, left, functionCaller) @@ -378,8 +378,8 @@ func (intr *treeInterpreter) execute(node parsing.ASTNode, value interface{}, fu } return nil, nil } - collected := []interface{}{} - var current interface{} + collected := []any{} + var current any for _, element := range sliceType { current, err = intr.execute(node.Children[1], element, functionCaller) if err != nil { @@ -401,7 +401,7 @@ func (intr *treeInterpreter) execute(node parsing.ASTNode, value interface{}, fu return intr.execute(node.Children[1], left, functionCaller) case parsing.ASTSlice: parts := node.Value.([]*int) - sliceType, ok := value.([]interface{}) + sliceType, ok := value.([]any) if !ok { if util.IsSliceType(value) { return intr.sliceWithReflection(node, value) @@ -427,15 +427,15 @@ func (intr *treeInterpreter) execute(node parsing.ASTNode, value interface{}, fu if err != nil { return nil, nil } - mapType, ok := left.(map[string]interface{}) + mapType, ok := left.(map[string]any) if !ok { return nil, nil } - values := []interface{}{} + values := []any{} for _, value := range mapType { values = append(values, value) } - collected := []interface{}{} + collected := []any{} for _, element := range values { current, err := intr.execute(node.Children[1], element, functionCaller) if err != nil { @@ -454,7 +454,7 @@ func extractField(value any, field string) (any, error) { if value == nil { return nil, nil } - if m, ok := value.(map[string]interface{}); ok { + if m, ok := value.(map[string]any); ok { return m[field], nil } return extractFieldUsingReflection(reflect.ValueOf(value), field) @@ -486,9 +486,9 @@ func extractFieldUsingReflection(value reflect.Value, field string) (any, error) return nil, nil } -func (intr *treeInterpreter) flattenWithReflection(value interface{}) (interface{}, error) { +func (intr *treeInterpreter) flattenWithReflection(value any) (any, error) { v := reflect.ValueOf(value) - flattened := []interface{}{} + flattened := []any{} for i := 0; i < v.Len(); i++ { element := v.Index(i).Interface() if reflect.TypeOf(element).Kind() == reflect.Slice { @@ -507,7 +507,7 @@ func (intr *treeInterpreter) flattenWithReflection(value interface{}) (interface return flattened, nil } -func (intr *treeInterpreter) sliceWithReflection(node parsing.ASTNode, value interface{}) (interface{}, error) { +func (intr *treeInterpreter) sliceWithReflection(node parsing.ASTNode, value any) (any, error) { v := reflect.ValueOf(value) parts := node.Value.([]*int) sliceParams := make([]util.SliceParam, 3) @@ -517,7 +517,7 @@ func (intr *treeInterpreter) sliceWithReflection(node parsing.ASTNode, value int sliceParams[i].N = *part } } - final := []interface{}{} + final := []any{} for i := 0; i < v.Len(); i++ { element := v.Index(i).Interface() final = append(final, element) @@ -525,9 +525,9 @@ func (intr *treeInterpreter) sliceWithReflection(node parsing.ASTNode, value int return util.Slice(final, sliceParams) } -func (intr *treeInterpreter) filterProjectionWithReflection(node parsing.ASTNode, value interface{}, functionCaller FunctionCaller) (interface{}, error) { +func (intr *treeInterpreter) filterProjectionWithReflection(node parsing.ASTNode, value any, functionCaller FunctionCaller) (any, error) { compareNode := node.Children[2] - collected := []interface{}{} + collected := []any{} v := reflect.ValueOf(value) for i := 0; i < v.Len(); i++ { element := v.Index(i).Interface() @@ -548,8 +548,8 @@ func (intr *treeInterpreter) filterProjectionWithReflection(node parsing.ASTNode return collected, nil } -func (intr *treeInterpreter) projectWithReflection(node parsing.ASTNode, value interface{}, functionCaller FunctionCaller) (interface{}, error) { - collected := []interface{}{} +func (intr *treeInterpreter) projectWithReflection(node parsing.ASTNode, value any, functionCaller FunctionCaller) (any, error) { + collected := []any{} v := reflect.ValueOf(value) for i := 0; i < v.Len(); i++ { element := v.Index(i).Interface() diff --git a/pkg/interpreter/interpreter_test.go b/pkg/interpreter/interpreter_test.go index 67c6422..8e8d015 100644 --- a/pkg/interpreter/interpreter_test.go +++ b/pkg/interpreter/interpreter_test.go @@ -43,7 +43,7 @@ type nestedSlice struct { A []sliceType } -func search(t *testing.T, expression string, data interface{}) (interface{}, error) { +func search(t *testing.T, expression string, data any) (any, error) { t.Helper() parser := parsing.NewParser() ast, err := parser.Parse(expression) @@ -56,7 +56,7 @@ func search(t *testing.T, expression string, data interface{}) (interface{}, err func TestCanSupportEmptyInterface(t *testing.T) { assert := assert.New(t) - data := make(map[string]interface{}) + data := make(map[string]any) data["foo"] = "bar" result, err := search(t, "foo", data) assert.Nil(err) @@ -84,7 +84,7 @@ func TestCanSupportStructWithSliceAll(t *testing.T) { data := sliceType{A: "foo", B: []scalars{{"f1", "b1"}, {"correct", "b2"}}} result, err := search(t, "B[].Foo", data) assert.Nil(err) - assert.Equal([]interface{}{"f1", "correct"}, result) + assert.Equal([]any{"f1", "correct"}, result) } func TestCanSupportStructWithSlicingExpression(t *testing.T) { @@ -92,7 +92,7 @@ func TestCanSupportStructWithSlicingExpression(t *testing.T) { data := sliceType{A: "foo", B: []scalars{{"f1", "b1"}, {"correct", "b2"}}} result, err := search(t, "B[:].Foo", data) assert.Nil(err) - assert.Equal([]interface{}{"f1", "correct"}, result) + assert.Equal([]any{"f1", "correct"}, result) } func TestCanSupportStructWithFilterProjection(t *testing.T) { @@ -100,7 +100,7 @@ func TestCanSupportStructWithFilterProjection(t *testing.T) { data := sliceType{A: "foo", B: []scalars{{"f1", "b1"}, {"correct", "b2"}}} result, err := search(t, "B[? `true` ].Foo", data) assert.Nil(err) - assert.Equal([]interface{}{"f1", "correct"}, result) + assert.Equal([]any{"f1", "correct"}, result) } func TestCanSupportStructWithSlice(t *testing.T) { @@ -162,7 +162,7 @@ func TestCanSupportFlattenNestedSlice(t *testing.T) { }} result, err := search(t, "A[].B[].Foo", data) assert.Nil(err) - assert.Equal([]interface{}{"f1a", "f1b", "f2a", "f2b"}, result) + assert.Equal([]any{"f1a", "f1b", "f2a", "f2b"}, result) } func TestCanSupportFlattenNestedEmptySlice(t *testing.T) { @@ -172,7 +172,7 @@ func TestCanSupportFlattenNestedEmptySlice(t *testing.T) { }} result, err := search(t, "A[].B[].Foo", data) assert.Nil(err) - assert.Equal([]interface{}{"a"}, result) + assert.Equal([]any{"a"}, result) } func TestCanSupportProjectionsWithStructs(t *testing.T) { @@ -182,7 +182,7 @@ func TestCanSupportProjectionsWithStructs(t *testing.T) { }} result, err := search(t, "A[*].A", data) assert.Nil(err) - assert.Equal([]interface{}{"first", "second", "third"}, result) + assert.Equal([]any{"first", "second", "third"}, result) } func TestCanSupportSliceOfStructsWithFunctions(t *testing.T) { @@ -230,7 +230,7 @@ func BenchmarkInterpretNestedStruct(b *testing.B) { func BenchmarkInterpretNestedMaps(b *testing.B) { assert := assert.New(b) jsonData := []byte(`{"fooasdfasdfasdfasdf": {"fooasdfasdfasdfasdf": {"fooasdfasdfasdfasdf": {"fooasdfasdfasdfasdf": "foobarbazqux"}}}}`) - var data interface{} + var data any err := json.Unmarshal(jsonData, &data) assert.Nil(err) intr := NewInterpreter(nil, nil) diff --git a/pkg/parsing/parser.go b/pkg/parsing/parser.go index 820b4b2..5ac2260 100644 --- a/pkg/parsing/parser.go +++ b/pkg/parsing/parser.go @@ -46,7 +46,7 @@ const ( // ASTNode represents the abstract syntax tree of a JMESPath expression. type ASTNode struct { NodeType astNodeType - Value interface{} + Value any Children []ASTNode } @@ -360,7 +360,7 @@ func (p *Parser) nud(token token) (ASTNode, error) { Value: token.value, }, nil case TOKJSONLiteral: - var parsed interface{} + var parsed any err := json.Unmarshal([]byte(token.value), &parsed) if err != nil { return ASTNode{}, err diff --git a/pkg/util/util.go b/pkg/util/util.go index 969b37a..1170c37 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -13,13 +13,13 @@ import ( // - An empty string array, or hash. // - The boolean value false. // - nil. -func IsFalse(value interface{}) bool { +func IsFalse(value any) bool { switch v := value.(type) { case bool: return !v - case []interface{}: + case []any: return len(v) == 0 - case map[string]interface{}: + case map[string]any: return len(v) == 0 case string: return len(v) == 0 @@ -50,7 +50,7 @@ func IsFalse(value interface{}) bool { // ObjsEqual is a generic object equality check. // It will take two arbitrary objects and recursively determine // if they are equal. -func ObjsEqual(left interface{}, right interface{}) bool { +func ObjsEqual(left any, right any) bool { return reflect.DeepEqual(left, right) } @@ -63,7 +63,7 @@ type SliceParam struct { } // Slice supports [start:stop:step] style slicing that's supported in JMESPath. -func Slice[T interface{} | rune](slice []T, parts []SliceParam) ([]T, error) { +func Slice[T any | rune](slice []T, parts []SliceParam) ([]T, error) { computed, err := computeSliceParams(len(slice), parts) if err != nil { return nil, err @@ -154,14 +154,14 @@ func capSlice(length int, actual int, step int) int { // ToArrayArray converts an empty interface type to a slice of slices. // If any element in the array cannot be converted, then nil is returned // along with a second value of false. -func ToArrayArray(data interface{}) ([][]interface{}, bool) { - result := [][]interface{}{} - arr, ok := data.([]interface{}) +func ToArrayArray(data any) ([][]any, bool) { + result := [][]any{} + arr, ok := data.([]any) if !ok { return nil, false } for _, item := range arr { - nested, ok := item.([]interface{}) + nested, ok := item.([]any) if !ok { return nil, false } @@ -173,9 +173,9 @@ func ToArrayArray(data interface{}) ([][]interface{}, bool) { // ToArrayNum converts an empty interface type to a slice of float64. // If any element in the array cannot be converted, then nil is returned // along with a second value of false. -func ToArrayNum(data interface{}) ([]float64, bool) { +func ToArrayNum(data any) ([]float64, bool) { // Is there a better way to do this with reflect? - if d, ok := data.([]interface{}); ok { + if d, ok := data.([]any); ok { result := make([]float64, len(d)) for i, el := range d { item, ok := el.(float64) @@ -194,9 +194,9 @@ func ToArrayNum(data interface{}) ([]float64, bool) { // along with a second value of false. If the input data could be entirely // converted, then the converted data, along with a second value of true, // will be returned. -func ToArrayStr(data interface{}) ([]string, bool) { +func ToArrayStr(data any) ([]string, bool) { // Is there a better way to do this with reflect? - if d, ok := data.([]interface{}); ok { + if d, ok := data.([]any); ok { result := make([]string, len(d)) for i, el := range d { item, ok := el.(string) @@ -214,7 +214,7 @@ func ToArrayStr(data interface{}) ([]string, bool) { // It expects the empty interface to represent a float64 JSON number. // If the empty interface cannot be converted or if the number // is not an integer, the function returns a second boolean value false. -func ToInteger(v interface{}) (int, bool) { +func ToInteger(v any) (int, bool) { if num, ok := v.(float64); ok { if math.Floor(num) != num { return 0, false @@ -225,7 +225,7 @@ func ToInteger(v interface{}) (int, bool) { } // ToNumber converts a numeric interface to a float64. -func ToNumber(v interface{}) (float64, bool) { +func ToNumber(v any) (float64, bool) { value := reflect.ValueOf(v) if value.CanFloat() { return value.Float(), true @@ -239,12 +239,12 @@ func ToNumber(v interface{}) (float64, bool) { return 0, false } -func ToPositiveInteger(v interface{}) (int, bool) { +func ToPositiveInteger(v any) (int, bool) { num, ok := ToInteger(v) return num, ok && num >= 0 } -func IsSliceType(v interface{}) bool { +func IsSliceType(v any) bool { if v == nil { return false } diff --git a/pkg/util/util_test.go b/pkg/util/util_test.go index b35b7bb..db0ec96 100644 --- a/pkg/util/util_test.go +++ b/pkg/util/util_test.go @@ -8,7 +8,7 @@ import ( func TestSlicePositiveStep(t *testing.T) { assert := assert.New(t) - input := make([]interface{}, 5) + input := make([]any, 5) input[0] = 0 input[1] = 1 input[2] = 2 @@ -23,9 +23,9 @@ func TestIsFalseJSONTypes(t *testing.T) { assert := assert.New(t) assert.True(IsFalse(false)) assert.True(IsFalse("")) - var empty []interface{} + var empty []any assert.True(IsFalse(empty)) - m := make(map[string]interface{}) + m := make(map[string]any) assert.True(IsFalse(m)) assert.True(IsFalse(nil)) } @@ -46,7 +46,7 @@ func TestIsFalseWithUserDefinedStructs(t *testing.T) { func TestIsFalseWithNilInterface(t *testing.T) { assert := assert.New(t) var a *int - var nilInterface interface{} = a + var nilInterface any = a assert.True(IsFalse(nilInterface)) } @@ -74,7 +74,7 @@ func TestObjsEqual(t *testing.T) { func TestToNumber(t *testing.T) { tests := []struct { name string - value interface{} + value any want float64 wantOk bool }{{