问题是带有map [string] interface {}类型字段的struct的xml.Unmarshal将失败并显示错误:
unknown type map[string]interface {}
{XMLName:{Space: Local:myStruct} Name:test Meta:map[]}
由于类型map [string] interface {}的元字段是我可以定义的,所以内部必须动态解组。
package main
import (
"encoding/xml"
"fmt"
)
func main() {
var myStruct MyStruct
// meta is as far as we know, inside meta, dynamic properties and nesting will happen
s := `<myStruct>
<name>test</name>
<meta>
<someProp>something</someProp>
<someOtherDynamic>
<name>test</name>
<somethingElse>test2</somethingElse>
<nested3>
<name>nested3</name>
<nested3elements>
<elem>ele1</elem>
<elem>ele2</elem>
</nested3elements>
</nested3>
</someOtherDynamic>
</meta>
</myStruct>`
err := xml.Unmarshal([]byte(s), &myStruct)
if err == nil {
fmt.Printf("%+v\n", myStruct)
} else {
fmt.Println(err)
fmt.Printf("%+v\n", myStruct)
}
}
type MyStruct struct {
XMLName xml.Name `xml:"myStruct"`
Name string `xml:"name"`
Meta map[string]interface{} `xml:"meta,omitempty"`
}
我在这里做了一个例子:http://play.golang.org/p/lTDJzXXPwT
我怎样才能做到这一点?
我的解决方法&#34;解决方案&#34;到目前为止:
http://play.golang.org/p/gQUlvkYl7k
基本上发生的是:
xml:",innerxml"
xml:"meta,omitempty"
注释添加MapContainer类型的MetaByte字段因此,在第一个xml.Unmarshal中,我们保存了元元素XML的字节切片。然后在我们的自定义xml unmarshal函数中,我们获取byteSlice并使用mxj包中的magic函数NewMapXml,并将struct的Meta字段设置为这个新创建的映射。
这要归功于天才制作了这个回购集https://github.com/clbanning/mxj,它可以从XML解组到地图。
更新了当前的最佳解决方案:
http://play.golang.org/p/_tw06klods
感谢Adam Vincze
答案 0 :(得分:2)
取决于你最后需要做什么,你可能想看看这个lib:https://github.com/clbanning/mxj
如果你实现一个自定义的UnmarshalXML函数,你可以做得更好一些func (m *MyStruct) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
var v struct {
XMLName xml.Name `xml:"myStruct"`
Name string `xml:"name"`
Meta struct {
Inner []byte `xml:",innerxml"`
} `xml:"meta"`
}
err := d.DecodeElement(&v, &start)
if err != nil {
return err
}
m.Name = v.Name
myMap := make(map[string]interface{})
// ... do the mxj magic here ... -
// fill myMap
m.Meta = myMap
return nil
}
type MyStruct struct {
Name string
Meta map[string]interface{}
}
`
让你的MyStruct保持干净整洁