gpt4 book ai didi

go - Go 中具有动态类型(空接口(interface))的 XML Unmarshal

转载 作者:数据小太阳 更新时间:2023-10-29 03:11:11 27 4
gpt4 key购买 nike

我需要解析具有动态元素的 XML 消息,因此我使用类型为 interface{} 的元素在我的 Message 结构中表示它。

一旦我知道了这个动态元素的类型(在运行时),我就初始化一个消息结构,然后尝试解码 XML 消息。但是,动态元素的内容并未解码。

这是一个 Go Playground,其中包含我正在努力实现的目标、评论以及实际输出与预期输出:https://play.golang.org/p/eKVetUPmVI2

我尝试了几种变体,但无法按预期进行解码。谁能帮助我理解为什么会出现这种行为以及如何让它发挥作用?提前致谢。

代码(以防有一天 Go Playground 链接断开):

package main

import "fmt"
import "encoding/xml"

// XML root
type Message struct {
XMLName xml.Name `xml:"message"`
Operation Operation `xml:"operation"`
}

// An Operation can contain either a Create or an Update element
type Operation struct {
Create *Create `xml:"create"`
Update *Update `xml:"update"`
}

// Doesn't matter...
type Create struct{}

// Update contains a Color element or Any other element (we only know its type during runtime)
type Update struct {
Color *Color `xml:"color"`
Other Any
}

// Doesn't matter...
type Color struct{}

type Any interface{}

var xmlStr = []byte(`<message>
<operation>
<update>
<size>
<width>1000</width>
</size>
</update>
</operation>
</message>`)

func main() {
// At this point we already know what to expect to receive in Other, so we can declare a struct for its content (Size)
type Size struct {
XMLName xml.Name `xml:"size"`
Width string `xml:"width"`
}

// Unmarshal
msg := &Message{
Operation: Operation{
Update: &Update{
Other: &Size{}, // Here I'm setting Other to Size, so I would expect Go to unmarshal the <size> contents into it
},
},
}
if err := xml.Unmarshal(xmlStr, msg); err != nil {
fmt.Println(err)
}

// Marshal again
b, err := xml.MarshalIndent(msg, "", " ")
if err != nil {
fmt.Println(err)
}

fmt.Printf("expected:\n\n%s\n\n", xmlStr)
fmt.Printf("actual:\n\n%s", string(b))
}

最佳答案

根据 encoding/xml 包文档:

If the XML element contains a sub-element that hasn't matched any of the above rules and the struct has a field with tag ",any", unmarshal maps the sub-element to that struct field.

对您的代码进行一个小的更新即可使其按预期工作:

xml:",any" 标记添加到您的 Other 字段定义中。

为了清理代码,我还会删除 Any 类型,您不需要它。您可以将 Other 字段定义更改为带有标记 xml:",any" 的类型 interface{} 并完成同样的事情。

像这样:

Other interface{} `xml:",any"`

执行并查看捕获的“1000”。

我建议更新您的问题以直接包含您的代码,以便人们更容易找到/搜索/阅读您的问题。拥有 Go playground 链接也很有用,因此读者可以快速运行/调整/测试示例。

关于go - Go 中具有动态类型(空接口(interface))的 XML Unmarshal,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51450987/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com