Commit 4dce7f85 authored by Russ Cox's avatar Russ Cox

encoding/xml: accept chains of interfaces and pointers

Fixes #6556.

R=golang-dev, iant, adg
CC=golang-dev
https://golang.org/cl/14747043
parent e39eda13
...@@ -354,18 +354,19 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplat ...@@ -354,18 +354,19 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplat
return nil return nil
} }
kind := val.Kind() // Drill into interfaces and pointers.
typ := val.Type() // This can turn into an infinite loop given a cyclic chain,
// but it matches the Go 1 behavior.
// Drill into pointers/interfaces for val.Kind() == reflect.Interface || val.Kind() == reflect.Ptr {
if kind == reflect.Ptr || kind == reflect.Interface {
if val.IsNil() { if val.IsNil() {
return nil return nil
} }
val = val.Elem() val = val.Elem()
typ = val.Type()
} }
kind := val.Kind()
typ := val.Type()
// Check for marshaler. // Check for marshaler.
if val.CanInterface() && typ.Implements(marshalerType) { if val.CanInterface() && typ.Implements(marshalerType) {
return p.marshalInterface(val.Interface().(Marshaler), defaultStart(typ, finfo, startTemplate)) return p.marshalInterface(val.Interface().(Marshaler), defaultStart(typ, finfo, startTemplate))
......
...@@ -314,6 +314,10 @@ type MarshalerStruct struct { ...@@ -314,6 +314,10 @@ type MarshalerStruct struct {
Foo MyMarshalerAttrTest `xml:",attr"` Foo MyMarshalerAttrTest `xml:",attr"`
} }
func ifaceptr(x interface{}) interface{} {
return &x
}
var ( var (
nameAttr = "Sarah" nameAttr = "Sarah"
ageAttr = uint(12) ageAttr = uint(12)
...@@ -356,6 +360,7 @@ var marshalTests = []struct { ...@@ -356,6 +360,7 @@ var marshalTests = []struct {
{Value: &Plain{NamedType("potato")}, ExpectXML: `<Plain><V>potato</V></Plain>`}, {Value: &Plain{NamedType("potato")}, ExpectXML: `<Plain><V>potato</V></Plain>`},
{Value: &Plain{[]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`}, {Value: &Plain{[]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},
{Value: &Plain{[3]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`}, {Value: &Plain{[3]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},
{Value: ifaceptr(true), MarshalOnly: true, ExpectXML: `<bool>true</bool>`},
// Test time. // Test time.
{ {
...@@ -1113,3 +1118,34 @@ func BenchmarkUnmarshal(b *testing.B) { ...@@ -1113,3 +1118,34 @@ func BenchmarkUnmarshal(b *testing.B) {
Unmarshal(xml, &Feed{}) Unmarshal(xml, &Feed{})
} }
} }
// golang.org/issue/6556
func TestStructPointerMarshal(t *testing.T) {
type A struct {
XMLName string `xml:"a"`
B []interface{}
}
type C struct {
XMLName Name
Value string `xml:"value"`
}
a := new(A)
a.B = append(a.B, &C{
XMLName: Name{Local: "c"},
Value: "x",
})
b, err := Marshal(a)
if err != nil {
t.Fatal(err)
}
if x := string(b); x != "<a><c><value>x</value></c></a>" {
t.Fatal(x)
}
var v A
err = Unmarshal(b, &v)
if err != nil {
t.Fatal(err)
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment