fix decode slice in zero fields false case
diff --git a/mapstructure.go b/mapstructure.go index bd46603..1595982 100644 --- a/mapstructure.go +++ b/mapstructure.go
@@ -606,6 +606,9 @@ for i := 0; i < dataVal.Len(); i++ { currentData := dataVal.Index(i).Interface() + for valSlice.Len() <= i { + valSlice = reflect.Append(valSlice, reflect.Zero(valElemType)) + } currentField := valSlice.Index(i) fieldName := fmt.Sprintf("%s[%d]", name, i)
diff --git a/mapstructure_bugs_test.go b/mapstructure_bugs_test.go index 2e210ca..08e4956 100644 --- a/mapstructure_bugs_test.go +++ b/mapstructure_bugs_test.go
@@ -59,7 +59,7 @@ }, } - result:=NestedPointer{ + result := NestedPointer{ Vbar: &Basic{ Vuint: 42, }, @@ -96,10 +96,9 @@ } - type NestedSlice struct { - Vfoo string - Vbars []Basic + Vfoo string + Vbars []Basic Vempty []Basic } @@ -110,16 +109,16 @@ input := map[string]interface{}{ "vfoo": "foo", "vbars": []map[string]interface{}{ - { "vstring": "foo", "vint": 42, "vbool": true }, - { "vint": 42, "vbool": true }, + {"vstring": "foo", "vint": 42, "vbool": true}, + {"vint": 42, "vbool": true}, }, "vempty": []map[string]interface{}{ - { "vstring": "foo", "vint": 42, "vbool": true }, - { "vint": 42, "vbool": true }, + {"vstring": "foo", "vint": 42, "vbool": true}, + {"vint": 42, "vbool": true}, }, } - result:=NestedSlice{ + result := NestedSlice{ Vbars: []Basic{ {Vuint: 42}, {Vstring: "foo"}, @@ -141,7 +140,6 @@ if result.Vbars[0].Vuint != 42 { t.Errorf("vuint value should be 42: %#v", result.Vbars[0].Vuint) } - } // #48 workaround @@ -157,7 +155,7 @@ }, } - result:=Nested{ + result := Nested{ Vbar: Basic{ Vuint: 42, }, @@ -192,4 +190,71 @@ t.Errorf("vuint value should be 42: %#v", result.Vbar.Vuint) } -} \ No newline at end of file +} + +// #67 panic() on extending slices (decodeSlice with disabled ZeroValues) +func TestDecodeSliceToEmptySliceWOZeroing(t *testing.T) { + t.Parallel() + + type TestStruct struct { + Vfoo []string + } + + decode := func(m interface{}, rawVal interface{}) error { + config := &DecoderConfig{ + Metadata: nil, + Result: rawVal, + ZeroFields: false, + } + + decoder, err := NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(m) + } + + { + input := map[string]interface{}{ + "vfoo": []string{"1"}, + } + + result := &TestStruct{} + + err := decode(input, &result) + if err != nil { + t.Fatalf("got an err: %s", err.Error()) + } + } + + { + input := map[string]interface{}{ + "vfoo": []string{"1"}, + } + + result := &TestStruct{ + Vfoo: []string{}, + } + + err := decode(input, &result) + if err != nil { + t.Fatalf("got an err: %s", err.Error()) + } + } + + { + input := map[string]interface{}{ + "vfoo": []string{"2", "3"}, + } + + result := &TestStruct{ + Vfoo: []string{"1"}, + } + + err := decode(input, &result) + if err != nil { + t.Fatalf("got an err: %s", err.Error()) + } + } +}