Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions deepobject.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,16 @@ func UnmarshalDeepObject(dst interface{}, paramName string, params url.Values) e
if strings.HasPrefix(pName, searchStr) {
// trim the parameter name from the full name.
pName = pName[len(paramName):]
fieldNames = append(fieldNames, pName)
if len(pValues) != 1 {
return fmt.Errorf("%s has multiple values", pName)
if len(pValues) == 1 {
fieldNames = append(fieldNames, pName)
fieldValues = append(fieldValues, pValues[0])
} else {
// Non-indexed array format: expand repeated keys into indexed entries
for i, value := range pValues {
fieldNames = append(fieldNames, pName+"["+strconv.Itoa(i)+"]")
fieldValues = append(fieldValues, value)
}
}
fieldValues = append(fieldValues, pValues[0])
}
}

Expand Down
35 changes: 35 additions & 0 deletions deepobject_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,38 @@ func TestDeepObject_ArrayOfObjects(t *testing.T) {
assert.Equal(t, "second", dstArray[1].Name)
assert.Equal(t, "value2", dstArray[1].Value)
}

func TestDeepObject_NonIndexedArray(t *testing.T) {
t.Run("primitive string array", func(t *testing.T) {
params := url.Values{}
params.Add("p[vals]", "a")
params.Add("p[vals]", "b")

type Obj struct {
Vals []string `json:"vals"`
}

var dst Obj
err := UnmarshalDeepObject(&dst, "p", params)
require.NoError(t, err)
assert.Equal(t, []string{"a", "b"}, dst.Vals)
})

t.Run("object with mixed scalar and non-indexed array", func(t *testing.T) {
params := url.Values{}
params.Set("p[op]", "eq")
params.Add("p[vals]", "a")
params.Add("p[vals]", "b")

type Filter struct {
Op string `json:"op"`
Vals []string `json:"vals"`
}

var dst Filter
err := UnmarshalDeepObject(&dst, "p", params)
require.NoError(t, err)
assert.Equal(t, "eq", dst.Op)
assert.Equal(t, []string{"a", "b"}, dst.Vals)
})
}