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, "dat", "2")
```

The initial data object still needs to be a `map[string]interface{}`
type.
  • Loading branch information
cmurphy committed Sep 18, 2023
1 parent f6f8c00 commit 408ec3f
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 5 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
32 changes: 31 additions & 1 deletion pkg/data/values_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,44 @@ 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: "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 408ec3f

Please sign in to comment.