Skip to content

Commit

Permalink
Fix: decode nil value in slice decoder (#2102)
Browse files Browse the repository at this point in the history
  • Loading branch information
kamingchan authored May 7, 2022
1 parent aef4dd3 commit 412b44a
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 2 deletions.
14 changes: 12 additions & 2 deletions common/structure/structure.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,19 @@ func (d *Decoder) decodeSlice(name string, data any, val reflect.Value) error {
for valSlice.Len() <= i {
valSlice = reflect.Append(valSlice, reflect.Zero(valElemType))
}
currentField := valSlice.Index(i)

fieldName := fmt.Sprintf("%s[%d]", name, i)
if currentData == nil {
// in weakly type mode, null will convert to zero value
if d.option.WeaklyTypedInput {
continue
}
// in non-weakly type mode, null will convert to nil if element's zero value is nil, otherwise return an error
if elemKind := valElemType.Kind(); elemKind == reflect.Map || elemKind == reflect.Slice {
continue
}
return fmt.Errorf("'%s' can not be null", fieldName)
}
currentField := valSlice.Index(i)
if err := d.decode(fieldName, currentData, currentField); err != nil {
return err
}
Expand Down
42 changes: 42 additions & 0 deletions common/structure/structure_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,45 @@ func TestStructure_Nest(t *testing.T) {
assert.Nil(t, err)
assert.Equal(t, s.BazOptional, goal)
}

func TestStructure_SliceNilValue(t *testing.T) {
rawMap := map[string]any{
"foo": 1,
"bar": []any{"bar", nil},
}

goal := &BazSlice{
Foo: 1,
Bar: []string{"bar", ""},
}

s := &BazSlice{}
err := weakTypeDecoder.Decode(rawMap, s)
assert.Nil(t, err)
assert.Equal(t, goal.Bar, s.Bar)

s = &BazSlice{}
err = decoder.Decode(rawMap, s)
assert.NotNil(t, err)
}

func TestStructure_SliceNilValueComplex(t *testing.T) {
rawMap := map[string]any{
"bar": []any{map[string]any{"bar": "foo"}, nil},
}

s := &struct {
Bar []map[string]any `test:"bar"`
}{}

err := decoder.Decode(rawMap, s)
assert.Nil(t, err)
assert.Nil(t, s.Bar[1])

ss := &struct {
Bar []Baz `test:"bar"`
}{}

err = decoder.Decode(rawMap, ss)
assert.NotNil(t, err)
}

0 comments on commit 412b44a

Please sign in to comment.