#48: fixes for ptr and slice cases
diff --git a/mapstructure.go b/mapstructure.go
index a554e79..81b0c01 100644
--- a/mapstructure.go
+++ b/mapstructure.go
@@ -546,7 +546,12 @@
// into that. Then set the value of the pointer to this type.
valType := val.Type()
valElemType := valType.Elem()
- realVal := reflect.New(valElemType)
+
+ realVal:=val
+ if realVal.IsNil() || d.config.ZeroFields {
+ realVal = reflect.New(valElemType)
+ }
+
if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil {
return err
}
@@ -562,20 +567,24 @@
valElemType := valType.Elem()
sliceType := reflect.SliceOf(valElemType)
- // Check input type
- if dataValKind != reflect.Array && dataValKind != reflect.Slice {
- // Accept empty map instead of array/slice in weakly typed mode
- if d.config.WeaklyTypedInput && dataVal.Kind() == reflect.Map && dataVal.Len() == 0 {
- val.Set(reflect.MakeSlice(sliceType, 0, 0))
- return nil
- } else {
- return fmt.Errorf(
- "'%s': source data must be an array or slice, got %s", name, dataValKind)
- }
- }
+ valSlice:=val
+ if valSlice.IsNil() || d.config.ZeroFields {
- // Make a new slice to hold our result, same size as the original data.
- valSlice := reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len())
+ // Check input type
+ if dataValKind != reflect.Array && dataValKind != reflect.Slice {
+ // Accept empty map instead of array/slice in weakly typed mode
+ if d.config.WeaklyTypedInput && dataVal.Kind() == reflect.Map && dataVal.Len() == 0 {
+ val.Set(reflect.MakeSlice(sliceType, 0, 0))
+ return nil
+ } else {
+ return fmt.Errorf(
+ "'%s': source data must be an array or slice, got %s", name, dataValKind)
+ }
+ }
+
+ // Make a new slice to hold our result, same size as the original data.
+ valSlice = reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len())
+ }
// Accumulate any errors
errors := make([]string, 0)
diff --git a/mapstructure_bugs_test.go b/mapstructure_bugs_test.go
index c6b8697..2e210ca 100644
--- a/mapstructure_bugs_test.go
+++ b/mapstructure_bugs_test.go
@@ -46,6 +46,7 @@
}
}
+// #48
func TestNestedTypePointerWithDefaults(t *testing.T) {
t.Parallel()
@@ -90,12 +91,60 @@
// this is the error
if result.Vbar.Vuint != 42 {
- t.Errorf("vuint value should be 42: %#v", result.Vbar.Vint)
+ t.Errorf("vuint value should be 42: %#v", result.Vbar.Vuint)
}
}
+type NestedSlice struct {
+ Vfoo string
+ Vbars []Basic
+ Vempty []Basic
+}
+
+// #48
+func TestNestedTypeSliceWithDefaults(t *testing.T) {
+ t.Parallel()
+
+ input := map[string]interface{}{
+ "vfoo": "foo",
+ "vbars": []map[string]interface{}{
+ { "vstring": "foo", "vint": 42, "vbool": true },
+ { "vint": 42, "vbool": true },
+ },
+ "vempty": []map[string]interface{}{
+ { "vstring": "foo", "vint": 42, "vbool": true },
+ { "vint": 42, "vbool": true },
+ },
+ }
+
+ result:=NestedSlice{
+ Vbars: []Basic{
+ {Vuint: 42},
+ {Vstring: "foo"},
+ },
+ }
+ err := Decode(input, &result)
+ if err != nil {
+ t.Fatalf("got an err: %s", err.Error())
+ }
+
+ if result.Vfoo != "foo" {
+ t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
+ }
+
+ if result.Vbars[0].Vstring != "foo" {
+ t.Errorf("vstring value should be 'foo': %#v", result.Vbars[0].Vstring)
+ }
+ // this is the error
+ if result.Vbars[0].Vuint != 42 {
+ t.Errorf("vuint value should be 42: %#v", result.Vbars[0].Vuint)
+ }
+
+}
+
+// #48 workaround
func TestNestedTypeWithDefaults(t *testing.T) {
t.Parallel()
@@ -140,7 +189,7 @@
// this is the error
if result.Vbar.Vuint != 42 {
- t.Errorf("vuint value should be 42: %#v", result.Vbar.Vint)
+ t.Errorf("vuint value should be 42: %#v", result.Vbar.Vuint)
}
}
\ No newline at end of file