执行:XML 将嵌套结构解组到接口{}
Go: XML Unmarshal Nested Structs into interface{}
我有 Python 的背景,这是我第一次正式涉足 Go,所以我认为事情还没有进展顺利。
我目前正在 Go 中实现 Affiliate Window XML API。 API 遵循请求和响应的标准结构,因此为此,我试图让事情保持干燥。信封总是有相同的结构,像这样:
<Envelope>
<Header></Header>
<Body></Body>
</Envelope>
内容 Header
和 Body
将根据我的请求和响应而有所不同,所以我创建了一个基础 Envelope
struct
type Envelope struct {
XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Envelope"`
NS1 string `xml:"xmlns:ns1,attr"`
XSD string `xml:"xmlns:xsd,attr"`
Header interface{} `xml:"http://schemas.xmlsoap.org/soap/envelope/ Header"`
Body interface{} `xml:"Body"`
}
这对于编组请求的 XML 非常有效,但我在解组时遇到问题:
func NewResponseEnvelope(body interface{}) *Envelope {
envelope := NewEnvelope()
envelope.Header = &ResponseHeader{}
envelope.Body = body
return envelope
}
func main() {
responseBody := &GetMerchantListResponseBody{}
responseEnvelope := NewResponseEnvelope(responseBody)
b := bytes.NewBufferString(response)
xml.NewDecoder(b).Decode(responseEnvelope)
fmt.Println(responseEnvelope.Header.Quota) // Why can't I access this?
}
这个 http://play.golang.org/p/v-MkfEyFPM 可能用代码比我用文字更好地描述了问题 :p
谢谢,
克里斯
Envelope
结构中 Header
字段的类型是 interface{}
,它是 而不是 一个 struct
所以你不能引用它的任何字段。
为了引用名为 Quota
的字段,您必须使用包含 Quota
字段的静态类型声明 Header
,如下所示:
type HeaderStruct struct {
Quota string
}
type Envelope struct {
// other fields omitted
Header HeaderStruct
}
如果您不知道它将是什么类型或者您不能提交单一类型,您可以将其保留为 interface{}
,但您必须使用 Type switches or Type assertion在运行时将其转换为静态类型,后者看起来像这样:
headerStruct, ok := responseEnvelope.Header.(HeaderStruct)
// if ok is true, headerStruct is of type HeaderStruct
// else responseEnvelope.Header is not of type HeaderStruct
另一种选择是使用反射来访问 Envelope.Header
值的命名字段,但如果可能,请尝试以其他方式解决它。如果您有兴趣了解有关 Go 中反射的更多信息,我建议您先阅读 The Laws of Reflection 博客 post。
我有 Python 的背景,这是我第一次正式涉足 Go,所以我认为事情还没有进展顺利。
我目前正在 Go 中实现 Affiliate Window XML API。 API 遵循请求和响应的标准结构,因此为此,我试图让事情保持干燥。信封总是有相同的结构,像这样:
<Envelope>
<Header></Header>
<Body></Body>
</Envelope>
内容 Header
和 Body
将根据我的请求和响应而有所不同,所以我创建了一个基础 Envelope
struct
type Envelope struct {
XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Envelope"`
NS1 string `xml:"xmlns:ns1,attr"`
XSD string `xml:"xmlns:xsd,attr"`
Header interface{} `xml:"http://schemas.xmlsoap.org/soap/envelope/ Header"`
Body interface{} `xml:"Body"`
}
这对于编组请求的 XML 非常有效,但我在解组时遇到问题:
func NewResponseEnvelope(body interface{}) *Envelope {
envelope := NewEnvelope()
envelope.Header = &ResponseHeader{}
envelope.Body = body
return envelope
}
func main() {
responseBody := &GetMerchantListResponseBody{}
responseEnvelope := NewResponseEnvelope(responseBody)
b := bytes.NewBufferString(response)
xml.NewDecoder(b).Decode(responseEnvelope)
fmt.Println(responseEnvelope.Header.Quota) // Why can't I access this?
}
这个 http://play.golang.org/p/v-MkfEyFPM 可能用代码比我用文字更好地描述了问题 :p
谢谢,
克里斯
Envelope
结构中 Header
字段的类型是 interface{}
,它是 而不是 一个 struct
所以你不能引用它的任何字段。
为了引用名为 Quota
的字段,您必须使用包含 Quota
字段的静态类型声明 Header
,如下所示:
type HeaderStruct struct {
Quota string
}
type Envelope struct {
// other fields omitted
Header HeaderStruct
}
如果您不知道它将是什么类型或者您不能提交单一类型,您可以将其保留为 interface{}
,但您必须使用 Type switches or Type assertion在运行时将其转换为静态类型,后者看起来像这样:
headerStruct, ok := responseEnvelope.Header.(HeaderStruct)
// if ok is true, headerStruct is of type HeaderStruct
// else responseEnvelope.Header is not of type HeaderStruct
另一种选择是使用反射来访问 Envelope.Header
值的命名字段,但如果可能,请尝试以其他方式解决它。如果您有兴趣了解有关 Go 中反射的更多信息,我建议您先阅读 The Laws of Reflection 博客 post。