Skip to content

Commit

Permalink
Add support for getting array index in GetValue
Browse files Browse the repository at this point in the history
Add the ability to use an index number to get an item out of a slice.

The number will still be a string representation of an integer. For
example, to get the last element from a nested slice like:

```
data := map[string]interface{}{
    "data": []interface{}{
        "first",
        "second",
        "third",
    },
}
```

Use keys like

```
val := GetValues(data, "data", "2")
```
  • Loading branch information
cmurphy committed Sep 22, 2023
1 parent 6d698c5 commit ac940a2
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 6 deletions.
32 changes: 28 additions & 4 deletions pkg/data/values.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package data

import (
"strconv"
)

func RemoveValue(data map[string]interface{}, keys ...string) (interface{}, bool) {
for i, key := range keys {
if i == len(keys)-1 {
Expand All @@ -18,18 +22,38 @@ func GetValueN(data map[string]interface{}, keys ...string) interface{} {
return val
}

func GetValue(data map[string]interface{}, keys ...string) (interface{}, bool) {
func GetValue(data interface{}, keys ...string) (interface{}, bool) {
for i, key := range keys {
if i == len(keys)-1 {
val, ok := data[key]
return val, ok
if dataMap, ok := data.(map[string]interface{}); ok {
val, ok := dataMap[key]
return val, ok
}
if dataSlice, ok := data.([]interface{}); ok {
return itemByIndex(dataSlice, key)
}
}
if dataMap, ok := data.(map[string]interface{}); ok {
data, _ = dataMap[key]
} else if dataSlice, ok := data.([]interface{}); ok {
data, _ = itemByIndex(dataSlice, key)
}
data, _ = data[key].(map[string]interface{})
}

return nil, false
}

func itemByIndex(dataSlice []interface{}, key string) (interface{}, bool) {
keyInt, err := strconv.Atoi(key)
if err != nil {
return nil, false
}
if keyInt >= len(dataSlice) || keyInt < 0 {
return nil, false
}
return dataSlice[keyInt], true
}

func PutValue(data map[string]interface{}, val interface{}, keys ...string) {
if data == nil {
return
Expand Down
45 changes: 43 additions & 2 deletions pkg/data/values_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ func TestGetValue(t *testing.T) {
t.Parallel()
tests := []struct {
name string
data map[string]interface{}
data interface{}
keys []string
wantValue interface{}
wantSuccess bool
Expand Down Expand Up @@ -70,14 +70,55 @@ func TestGetValue(t *testing.T) {
name: "get index of slice",
data: map[string]interface{}{
"parent": map[string]interface{}{
"children": []string{
"children": []interface{}{
"alice",
"bob",
"eve",
},
},
},
keys: []string{"parent", "children", "2"},
wantValue: "eve",
wantSuccess: true,
},
{
name: "get index of top levelslice",
data: []interface{}{
"alice",
"bob",
"eve",
},
keys: []string{"2"},
wantValue: "eve",
wantSuccess: true,
},
{
name: "index is too big",
data: map[string]interface{}{
"parent": map[string]interface{}{
"children": []interface{}{
"alice",
"bob",
"eve",
},
},
},
keys: []string{"parent", "children", "3"},
wantValue: nil,
wantSuccess: false,
},
{
name: "index is negative",
data: map[string]interface{}{
"parent": map[string]interface{}{
"children": []interface{}{
"alice",
"bob",
"eve",
},
},
},
keys: []string{"parent", "children", "-3"},
wantValue: nil,
wantSuccess: false,
},
Expand Down

0 comments on commit ac940a2

Please sign in to comment.