Skip to content

Commit 16f22f7

Browse files
committed
encoding/xml: fix 'unsupported type' error on interface{} attributes
When given interface value that is actually a type implementing `encoding.TextMarshaler` or `xml.MarshalerAttr`, `marshalAttr` would return an `unsupported type` error. The cause of this is that pointer and interface values are dereferences after checking if the supported interfaces are implemented. Solve this by moving the dereference of the pointer and interface values to the start of the function, and update the test cases to test for this situation.
1 parent 740a490 commit 16f22f7

File tree

2 files changed

+18
-9
lines changed

2 files changed

+18
-9
lines changed

src/encoding/xml/marshal.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,15 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplat
555555

556556
// marshalAttr marshals an attribute with the given name and value, adding to start.Attr.
557557
func (p *printer) marshalAttr(start *StartElement, name Name, val reflect.Value) error {
558+
// Dereference or skip nil pointer, interface values.
559+
switch val.Kind() {
560+
case reflect.Pointer, reflect.Interface:
561+
if val.IsNil() {
562+
return nil
563+
}
564+
val = val.Elem()
565+
}
566+
558567
if val.CanInterface() && val.Type().Implements(marshalerAttrType) {
559568
attr, err := val.Interface().(MarshalerAttr).MarshalXMLAttr(name)
560569
if err != nil {
@@ -601,15 +610,6 @@ func (p *printer) marshalAttr(start *StartElement, name Name, val reflect.Value)
601610
}
602611
}
603612

604-
// Dereference or skip nil pointer, interface values.
605-
switch val.Kind() {
606-
case reflect.Pointer, reflect.Interface:
607-
if val.IsNil() {
608-
return nil
609-
}
610-
val = val.Elem()
611-
}
612-
613613
// Walk slices.
614614
if val.Kind() == reflect.Slice && val.Type().Elem().Kind() != reflect.Uint8 {
615615
n := val.Len()

src/encoding/xml/marshal_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,10 @@ type MarshalerStruct struct {
343343
Foo MyMarshalerAttrTest `xml:",attr"`
344344
}
345345

346+
type IMarshalerStruct struct {
347+
Foo interface{} `xml:",attr"`
348+
}
349+
346350
type InnerStruct struct {
347351
XMLName Name `xml:"testns outer"`
348352
}
@@ -1252,6 +1256,11 @@ var marshalTests = []struct {
12521256
ExpectXML: `<MarshalerStruct Foo="hello world"></MarshalerStruct>`,
12531257
Value: &MarshalerStruct{},
12541258
},
1259+
{
1260+
ExpectXML: `<IMarshalerStruct Foo="hello world"></IMarshalerStruct>`,
1261+
Value: &IMarshalerStruct{Foo: &MyMarshalerAttrTest{}},
1262+
MarshalOnly: true,
1263+
},
12551264
{
12561265
ExpectXML: `<outer xmlns="testns" int="10"></outer>`,
12571266
Value: &OuterStruct{IntAttr: 10},

0 commit comments

Comments
 (0)