Skip to content

Commit

Permalink
Fix panic calling $distinct on array of arrays (#34)
Browse files Browse the repository at this point in the history
This fixes the following panic:
```
panic: runtime error: hash of unhashable type []interface {}
goroutine 176 [running]:
http://github.com/xiatechs/jsonata-go/jlib.Distinct ({0x1087cc0?, 0xc000661368?, 0x0?})
	/go/pkg/mod/github.com/xiatechs/[email protected]/jlib/array.go:61 +0x3e5
reflect.Value.call({0x10c10a0?, 0x1404a18?, 0x4cadbf?}, {0x1318275, 0x4}, {0xc000661590, 0x1, 0x0?})
	/usr/local/go/src/reflect/value.go:596 +0xce5
reflect.Value.Call({0x10c10a0?, 0x1404a18?, 0x1?}, {0xc000661590?, 0xc000661590?, 0x1087d00?})
	/usr/local/go/src/reflect/value.go:380 +0xb9
```
  • Loading branch information
Jarrah-libremfg authored Apr 17, 2024
1 parent 98098e0 commit 61ce7d5
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 5 deletions.
10 changes: 5 additions & 5 deletions jlib/array.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,14 @@ func Distinct(v reflect.Value) interface{} {
for i := 0; i < items.Len(); i++ {
item := jtypes.Resolve(items.Index(i))

if jtypes.IsMap(item) {
// We can't hash a map, so convert it to a
if jtypes.IsMap(item) || jtypes.IsArray(item) {
// We can't hash a map or array, so convert it to a
// string that is hashable
mapItem := fmt.Sprint(item.Interface())
if _, ok := visited[mapItem]; ok {
unhashableItem := fmt.Sprint(item.Interface())
if _, ok := visited[unhashableItem]; ok {
continue
}
visited[mapItem] = struct{}{}
visited[unhashableItem] = struct{}{}
distinctValues = reflect.Append(distinctValues, item)

continue
Expand Down
22 changes: 22 additions & 0 deletions jsonata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8028,6 +8028,28 @@ func TestTransform(t *testing.T) {
})
}

func TestUnhashableDistinct(t *testing.T) {
runTestCases(t, testdata.address, []*testCase{
{
Expression: `$distinct([["a", "b"]])`,
Output: []interface{}{
[]interface{}{
"a",
"b",
},
},
},
{
Expression: `$distinct([{"a": "b"}])`,
Output: []interface{}{
map[string]interface{}{
"a": "b",
},
},
},
})
}

// Helper functions

type compareFunc func(interface{}, interface{}) bool
Expand Down

0 comments on commit 61ce7d5

Please sign in to comment.