Make unmarshal to interface{} consistent with encoding/json
This commit is contained in:
@@ -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) {
|
||||
|
||||
+6
-5
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user