mirror of
https://github.com/golang/go
synced 2024-11-24 22:47:58 -07:00
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.
This commit is contained in:
parent
740a490f71
commit
16f22f78ca
@ -555,6 +555,15 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplat
|
||||
|
||||
// marshalAttr marshals an attribute with the given name and value, adding to start.Attr.
|
||||
func (p *printer) marshalAttr(start *StartElement, name Name, val reflect.Value) error {
|
||||
// Dereference or skip nil pointer, interface values.
|
||||
switch val.Kind() {
|
||||
case reflect.Pointer, reflect.Interface:
|
||||
if val.IsNil() {
|
||||
return nil
|
||||
}
|
||||
val = val.Elem()
|
||||
}
|
||||
|
||||
if val.CanInterface() && val.Type().Implements(marshalerAttrType) {
|
||||
attr, err := val.Interface().(MarshalerAttr).MarshalXMLAttr(name)
|
||||
if err != nil {
|
||||
@ -601,15 +610,6 @@ func (p *printer) marshalAttr(start *StartElement, name Name, val reflect.Value)
|
||||
}
|
||||
}
|
||||
|
||||
// Dereference or skip nil pointer, interface values.
|
||||
switch val.Kind() {
|
||||
case reflect.Pointer, reflect.Interface:
|
||||
if val.IsNil() {
|
||||
return nil
|
||||
}
|
||||
val = val.Elem()
|
||||
}
|
||||
|
||||
// Walk slices.
|
||||
if val.Kind() == reflect.Slice && val.Type().Elem().Kind() != reflect.Uint8 {
|
||||
n := val.Len()
|
||||
|
@ -343,6 +343,10 @@ type MarshalerStruct struct {
|
||||
Foo MyMarshalerAttrTest `xml:",attr"`
|
||||
}
|
||||
|
||||
type IMarshalerStruct struct {
|
||||
Foo interface{} `xml:",attr"`
|
||||
}
|
||||
|
||||
type InnerStruct struct {
|
||||
XMLName Name `xml:"testns outer"`
|
||||
}
|
||||
@ -1252,6 +1256,11 @@ var marshalTests = []struct {
|
||||
ExpectXML: `<MarshalerStruct Foo="hello world"></MarshalerStruct>`,
|
||||
Value: &MarshalerStruct{},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IMarshalerStruct Foo="hello world"></IMarshalerStruct>`,
|
||||
Value: &IMarshalerStruct{Foo: &MyMarshalerAttrTest{}},
|
||||
MarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<outer xmlns="testns" int="10"></outer>`,
|
||||
Value: &OuterStruct{IntAttr: 10},
|
||||
|
Loading…
Reference in New Issue
Block a user