Unmarshalling to instantiated empty interface in golang

huangapple go评论79阅读模式
英文:

Unmarshalling to instantiated empty interface in golang

问题

我正在尝试将其反序列化为一个空的go接口类型的变量。具体类型具有正确的xml标签,但由于某种原因,我无法反序列化xml值。它们只是变为空值。

以下是我想要实现的代码:

type Address struct {
    City, State string
}

type Result struct {
    XMLName xml.Name `xml:"Person"`
    Name    string   `xml:"FullName" json:"FullName"`
    Address interface{}
}

func main() {

    xmlAddress := &Address{}
    xmlResult := &Result{Name: "none", Address: xmlAddress}

    xmlData := `
        <Person>
            <FullName>Mike McCartney</FullName>
            <Address>
                <City>Austin</City>
                <State>Texas</State>
            </Address>
        </Person>
    `

    err := xml.Unmarshal([]byte(xmlData), xmlResult)

    // xmlResult = {"XMLName":{"Space":"","Local":"Person"},"FullName":"Mike McCartney","Address":{"City":"Austin","State":"Texas"}}
}

完整代码:https://play.golang.org/p/QXyoOPMFZr

但在我自己的带有实际xml和命名空间的示例中,它不起作用:

type Envelope struct {
    XMLName xml.Name `xml:"http://www.w3.org/2003/05/soap-envelope Envelope"`
    Body    Body     `xml:"http://www.w3.org/2003/05/soap-envelope Body"`
}

type Body struct {
    XMLName xml.Name `xml:"http://www.w3.org/2003/05/soap-envelope Body"`
    Content interface{}
}

type DebtorGetNameResponse struct {
    XMLName             xml.Name `xml:"http://e-conomic.com Debtor_GetNameResponse"`
    DebtorGetNameResult string   `xml:"Debtor_GetNameResult"`
}

func main() {

    xmlData := `
    <?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
        <soap:Body>
            <Debtor_GetNameResponse xmlns="http://e-conomic.com">
                <Debtor_GetNameResult>THIS SHOULD BE IN THE OUTPUT</Debtor_GetNameResult>
            </Debtor_GetNameResponse>
        </soap:Body>
    </soap:Envelope>`

    e := new(Envelope)
    res := new(DebtorGetNameResponse)
    e.Body = Body{Content: res}

    err := xml.Unmarshal([]byte(xmlData), e)

    // res = {"XMLName":{"Space":"","Local":""},"DebtorGetNameResult":""}
}

完整代码:https://play.golang.org/p/AsV1LGW1lR

英文:

I am trying to unmarshall into a variable of the empty go interface type. The concrete type has proper xml tags, but for some reason i cannot unmarshall the xml values. They just turn up empty.

This code does what I want to do:

type Address struct {
	City, State string
}

type Result struct {
	XMLName xml.Name `xml:&quot;Person&quot;`
	Name    string   `xml:&quot;FullName&quot; json:&quot;FullName&quot;`
	Address interface{}
}

func main() {

	xmlAddress := &amp;Address{}
	xmlResult := &amp;Result{Name: &quot;none&quot;, Address: xmlAddress}

	xmlData := `
    &lt;Person&gt;
        &lt;FullName&gt;Mike McCartney&lt;/FullName&gt;
        &lt;Address&gt;
            &lt;City&gt;Austin&lt;/City&gt;
            &lt;State&gt;Texas&lt;/State&gt;
        &lt;/Address&gt;
    &lt;/Person&gt;
`

	err := xml.Unmarshal([]byte(xmlData), xmlResult)

	// xmlResult = {&quot;XMLName&quot;:{&quot;Space&quot;:&quot;&quot;,&quot;Local&quot;:&quot;Person&quot;},&quot;FullName&quot;:&quot;Mike McCartney&quot;,&quot;Address&quot;:{&quot;City&quot;:&quot;Austin&quot;,&quot;State&quot;:&quot;Texas&quot;}}
}

Full code: https://play.golang.org/p/QXyoOPMFZr

But in my own example with actual xml with namespaces it doesn't work:

type Envelope struct {
	XMLName xml.Name `xml:&quot;http://www.w3.org/2003/05/soap-envelope Envelope&quot;`
	Body    Body     `xml:&quot;http://www.w3.org/2003/05/soap-envelope Body&quot;`
}

type Body struct {
	XMLName xml.Name `xml:&quot;http://www.w3.org/2003/05/soap-envelope Body&quot;`
	Content interface{}
}

type DebtorGetNameResponse struct {
	XMLName             xml.Name `xml:&quot;http://e-conomic.com Debtor_GetNameResponse&quot;`
	DebtorGetNameResult string   `xml:&quot;Debtor_GetNameResult&quot;`
}

func main() {

	xmlData := `
	&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
	&lt;soap:Envelope xmlns:soap=&quot;http://www.w3.org/2003/05/soap-envelope&quot;&gt;
		&lt;soap:Body&gt;
			&lt;Debtor_GetNameResponse xmlns=&quot;http://e-conomic.com&quot;&gt;
				&lt;Debtor_GetNameResult&gt;THIS SHOULD BE IN THE OUTPUT&lt;/Debtor_GetNameResult&gt;
			&lt;/Debtor_GetNameResponse&gt;
		&lt;/soap:Body&gt;
	&lt;/soap:Envelope&gt;`

	e := new(Envelope)
	res := new(DebtorGetNameResponse)
	e.Body = Body{Content: res}

	err := xml.Unmarshal([]byte(xmlData), e)

	// res = {&quot;XMLName&quot;:{&quot;Space&quot;:&quot;&quot;,&quot;Local&quot;:&quot;&quot;},&quot;DebtorGetNameResult&quot;:&quot;&quot;}
}

Full code: https://play.golang.org/p/AsV1LGW1lR

答案1

得分: 1

你需要将xml标签添加到你的interface{}中,例如:

Content interface{} `xml:"http://e-conomic.com Debtor_GetNameResponse"`

在你的另一个示例中,Address interface{}可以工作,因为它的名称与xml标签<Address></Address>相同,并且Unmarshal通过名称进行查找。

英文:

You need to add the xml tags to your interface{}, ie.

Content interface{} `xml:&quot;http://e-conomic.com Debtor_GetNameResponse&quot;`

Address interface{} in your other example works because its name is the same of the xml tag &lt;Address&gt;&lt;/Address&gt; and Unmarshal lookups by it.

huangapple
  • 本文由 发表于 2017年6月23日 21:24:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/44722580.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定