From 07b121f822dbaa8a2bb165951c0f8dfc1af4eba6 Mon Sep 17 00:00:00 2001 From: Earncef Sequeira Date: Wed, 7 Jul 2021 13:49:48 +0100 Subject: [PATCH] fix nested array access --- accessors.go | 32 +++++++++++++++++++++++--------- accessors_test.go | 19 +++++++++++++++++++ 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/accessors.go b/accessors.go index 80ad167..b193d51 100644 --- a/accessors.go +++ b/accessors.go @@ -116,9 +116,15 @@ func getKey(s string) (string, string) { func access(current interface{}, selector string, value interface{}, isSet bool) interface{} { thisSel, nextSel := getKey(selector) - index := -1 - if strings.Contains(thisSel, "[") { + indexes := []int{} + for strings.Contains(thisSel, "[") { + prevSel := thisSel + index := -1 index, thisSel = getIndex(thisSel) + indexes = append(indexes, index) + if prevSel == thisSel { + break + } } if curMap, ok := current.(Map); ok { @@ -134,7 +140,7 @@ func access(current interface{}, selector string, value interface{}, isSet bool) } _, ok := curMSI[thisSel].(map[string]interface{}) - if (curMSI[thisSel] == nil || !ok) && index == -1 && isSet { + if (curMSI[thisSel] == nil || !ok) && len(indexes) == 0 && isSet { curMSI[thisSel] = map[string]interface{}{} } @@ -144,15 +150,23 @@ func access(current interface{}, selector string, value interface{}, isSet bool) } // do we need to access the item of an array? - if index > -1 { - if array, ok := interSlice(current); ok { - if index < len(array) { - current = array[index] - } else { - current = nil + if len(indexes) > 0 { + num := len(indexes) + for num > 0 { + num-- + index := indexes[num] + indexes = indexes[:num] + if array, ok := interSlice(current); ok { + if index < len(array) { + current = array[index] + } else { + current = nil + break + } } } } + if nextSel != "" { current = access(current, nextSel, value, isSet) } diff --git a/accessors_test.go b/accessors_test.go index a3ee410..c43c18c 100644 --- a/accessors_test.go +++ b/accessors_test.go @@ -218,3 +218,22 @@ func TestAccessorsSet(t *testing.T) { assert.Equal(t, "Mat", m.Get("name").Data()) } + +func TestAccessorsNested(t *testing.T) { + d := objx.MustFromJSON(`{"values":[["test", "test1"], ["test2", {"name":"Mat"}, {"names": ["Captain", "Mat"]}]]}`) + + value := d.Get("values[0][0]").String() + assert.Equal(t, "test", value) + + value = d.Get("values[0][1]").String() + assert.Equal(t, "test1", value) + + value = d.Get("values[1][0]").String() + assert.Equal(t, "test2", value) + + value = d.Get("values[1][1].name").String() + assert.Equal(t, "Mat", value) + + value = d.Get("values[1][2].names[0]").String() + assert.Equal(t, "Captain", value) +}