Jelajahi Sumber

Only inherit map types if sufficiently flexible.

Fixes #39.
Gustavo Niemeyer 11 tahun lalu
induk
melakukan
f5f5cc19d1
2 mengubah file dengan 27 tambahan dan 11 penghapusan
  1. 11 6
      decode.go
  2. 16 5
      decode_test.go

+ 11 - 6
decode.go

@@ -191,7 +191,12 @@ type decoder struct {
 	terrors []string
 }
 
-var defaultMapType = reflect.TypeOf(map[interface{}]interface{}{})
+var (
+	mapItemType = reflect.TypeOf(MapItem{})
+	durationType = reflect.TypeOf(time.Duration(0))
+	defaultMapType = reflect.TypeOf(map[interface{}]interface{}{})
+	ifaceType = defaultMapType.Elem()
+)
 
 func newDecoder() *decoder {
 	d := &decoder{mapType: defaultMapType}
@@ -324,8 +329,6 @@ func resetMap(out reflect.Value) {
 	}
 }
 
-var durationType = reflect.TypeOf(time.Duration(0))
-
 func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
 	var tag string
 	var resolved interface{}
@@ -479,6 +482,8 @@ func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
 	return true
 }
 
+
+
 func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
 	switch out.Kind() {
 	case reflect.Struct:
@@ -509,7 +514,9 @@ func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
 	et := outt.Elem()
 
 	mapType := d.mapType
-	d.mapType = outt
+	if outt.Key() == ifaceType && outt.Elem() == ifaceType {
+		d.mapType = outt
+	}
 
 	if out.IsNil() {
 		out.Set(reflect.MakeMap(outt))
@@ -539,8 +546,6 @@ func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
 	return true
 }
 
-var mapItemType = reflect.TypeOf(MapItem{})
-
 func (d *decoder) mappingSlice(n *node, out reflect.Value) (good bool) {
 	outt := out.Type()
 	if outt.Elem() != mapItemType {

+ 16 - 5
decode_test.go

@@ -202,9 +202,6 @@ var unmarshalTests = []struct {
 	{
 		"a: {b: c}",
 		map[interface{}]interface{}{"a": map[interface{}]interface{}{"b": "c"}},
-	}, {
-		"a: {b: c}",
-		map[string]interface{}{"a": map[string]interface{}{"b": "c"}},
 	},
 
 	// Structs and type conversions.
@@ -409,8 +406,22 @@ var unmarshalTests = []struct {
 		"{b: 2, a: 1, d: 4, c: 3, sub: {e: 5}}",
 		&yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}},
 	},
+
+	// Issue #39.
+	{
+		"a:\n b:\n  c: d\n",
+		map[string]struct{ B interface{} }{"a": {map[interface{}]interface{}{"c": "d"}}},
+	},
+
+	// Custom map type.
+	{
+		"a: {b: c}",
+		M{"a": M{"b": "c"}},
+	},
 }
 
+type M map[interface{}]interface{}
+
 type inlineB struct {
 	B       int
 	inlineC `yaml:",inline"`
@@ -686,14 +697,14 @@ inlineSequenceMap:
 `
 
 func (s *S) TestMerge(c *C) {
-	var want = map[string]interface{}{
+	var want = map[interface{}]interface{}{
 		"x":     1,
 		"y":     2,
 		"r":     10,
 		"label": "center/big",
 	}
 
-	var m map[string]interface{}
+	var m map[interface{}]interface{}
 	err := yaml.Unmarshal([]byte(mergeTests), &m)
 	c.Assert(err, IsNil)
 	for name, test := range m {