diff --git a/internal/imported_tests/unmarshal_imported_test.go b/internal/imported_tests/unmarshal_imported_test.go index dda52d8..f450d50 100644 --- a/internal/imported_tests/unmarshal_imported_test.go +++ b/internal/imported_tests/unmarshal_imported_test.go @@ -126,10 +126,10 @@ func TestInterface(t *testing.T) { expected := Conf{ Name: "rui", Age: 18, - Inter: &NestedStruct{ - FirstName: "wang", - LastName: "jl", - Age: 100, + Inter: map[string]interface{}{ + "FirstName": "wang", + "LastName": "jl", + "Age": int64(100), }, } assert.Equal(t, expected, config) @@ -1663,25 +1663,21 @@ Age = 23 }, NilField: nil, InterfacePointerField: &s, - StructArrayField: []map[string]interface{}{ - { + StructArrayField: []interface{}{ + map[string]interface{}{ "Name": "Allen", "Age": int64(20), }, - { + map[string]interface{}{ "Name": "Jack", "Age": int64(23), }, }, } actual := OuterStruct{} - if err := toml.Unmarshal(doc, &actual); err == nil { - if !reflect.DeepEqual(actual, expected) { - t.Errorf("Bad unmarshal: expected %v, got %v", expected, actual) - } - } else { - t.Fatal(err) - } + err := toml.Unmarshal(doc, &actual) + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestUnmarshalToNonNilInterface(t *testing.T) { @@ -1727,8 +1723,8 @@ InnerField = "After4" var s interface{} = InnerStruct{"After"} expected := OuterStruct{ PrimitiveField: "Allen", - ArrayField: []int{1, 2, 3}, - StructField: InnerStruct{InnerField: "After1"}, + ArrayField: []interface{}{int64(1), int64(2), int64(3)}, + StructField: map[string]interface{}{"InnerField": "After1"}, MapField: map[string]interface{}{ "MapField1": []interface{}{int64(4), int64(5), int64(6)}, "MapField2": map[string]interface{}{ @@ -1736,12 +1732,12 @@ InnerField = "After4" }, "MapField3": false, }, - PointerField: &InnerStruct{InnerField: "After2"}, + PointerField: map[string]interface{}{"InnerField": "After2"}, NilField: nil, InterfacePointerField: &s, - StructArrayField: []InnerStruct{ - {InnerField: "After3"}, - {InnerField: "After4"}, + StructArrayField: []interface{}{ + map[string]interface{}{"InnerField": "After3"}, + map[string]interface{}{"InnerField": "After4"}, }, } actual := OuterStruct{ @@ -1763,13 +1759,10 @@ InnerField = "After4" {InnerField: "Before4"}, }, } - if err := toml.Unmarshal(doc, &actual); err == nil { - if !reflect.DeepEqual(actual, expected) { - t.Errorf("Bad unmarshal: expected %v, got %v", expected, actual) - } - } else { - t.Fatal(err) - } + + err := toml.Unmarshal(doc, &actual) + require.NoError(t, err) + assert.Equal(t, expected, actual) } func TestUnmarshalNil(t *testing.T) { diff --git a/targets.go b/targets.go index b11f57a..8595f09 100644 --- a/targets.go +++ b/targets.go @@ -129,10 +129,10 @@ func ensureSlice(t target) error { return t.set(reflect.MakeSlice(f.Type(), 0, 0)) } case reflect.Interface: - if f.IsNil() { + if f.IsNil() || f.Elem().Type() != sliceInterfaceType { return t.set(reflect.MakeSlice(sliceInterfaceType, 0, 0)) } - if f.Type().Elem().Kind() != reflect.Slice { + if f.Elem().Type().Kind() != reflect.Slice { return fmt.Errorf("interface is pointing to a %s, not a slice", f.Kind()) } case reflect.Ptr: @@ -152,6 +152,7 @@ func ensureSlice(t target) error { } var sliceInterfaceType = reflect.TypeOf([]interface{}{}) +var mapStringInterfaceType = reflect.TypeOf(map[string]interface{}{}) func setString(t target, v string) error { f := t.get() @@ -409,15 +410,15 @@ func initInterface(append bool, t target) error { panic("this should only be called on interfaces") } - if !x.IsNil() { + if !x.IsNil() && (x.Elem().Type() == sliceInterfaceType || x.Elem().Type() == mapStringInterfaceType) { return nil } var newElement reflect.Value if append { - newElement = reflect.MakeSlice(reflect.TypeOf([]interface{}{}), 0, 0) + newElement = reflect.MakeSlice(sliceInterfaceType, 0, 0) } else { - newElement = reflect.MakeMap(reflect.TypeOf(map[string]interface{}{})) + newElement = reflect.MakeMap(mapStringInterfaceType) } err := t.set(newElement) if err != nil { diff --git a/unmarshaler_test.go b/unmarshaler_test.go index af399eb..8e4c084 100644 --- a/unmarshaler_test.go +++ b/unmarshaler_test.go @@ -588,6 +588,31 @@ B = "data"`, } }, }, + { + desc: "interface holding a struct", + input: `[A] + B = "After"`, + gen: func() test { + type inner struct { + B interface{} + } + type doc struct { + A interface{} + } + return test{ + target: &doc{ + A: inner{ + B: "Before", + }, + }, + expected: &doc{ + A: map[string]interface{}{ + "B": "After", + }, + }, + } + }, + }, } for _, e := range examples {