omitempty在使用指针时在encoding/xml中不起作用吗?

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

omitempty does not work in encoding/xml when using pointers?

问题

我正在消费一个返回XML的REST API,并尝试对XML进行解组,但出现了似乎omitempty不起作用的问题。这是一个工作的XML文件示例:

<?xml version='1.0' encoding='UTF-8'?>
<customer uri="/api/customers/339/" id="339">
    <name>
        <first>Firstname</first>
        <last>Lastname</last>
    </name>
    <email>myemail@example.com</email>
    <billing>
        <address>
            <address1>123 Main St.</address1>
            <address2></address2>
            <city>Nowhere</city>
            <state>IA</state>
            <country>USA</country>
            <zip>12345</zip>
        </address>
    </billing>
</customer>

这是一个“错误”的记录示例:

<?xml version='1.0' encoding='UTF-8'?>
<customer uri="/api/customers/6848/" id="6848">
    <name>
        <first>Firstname</first>
        <last>Lastname</last>
    </name>
    <email/>
    <billing/>
</customer>

现在我已经设置好了我的结构体,如下所示:

type Customer struct {
    ID      int      `xml:"id,attr"`
    Name    *Name    `xml:"name,omitempty"`
    Billing *Billing `xml:"billing,omitempty"`
}

type Billing struct {
    Address *Address `xml:"address,omitempty"`
}

type Address struct {
    Address1 string `xml:"address1,omitempty"`
    Address2 string `xml:"address2,omitempty"`
    City     string `xml:"city,omitempty"`
    State    string `xml:"state,omitempty"`
    Country  string `xml:"country,omitempty"`
    Zip      string `xml:"zip,omitempty"`
}

type Name struct {
    First string `xml:"first"`
    Last  string `xml:"last"`
}

阅读所有记录时,当XML遵循第一个示例<billing></billing>的模式时,它可以正常工作,但当遇到类似<billing/>的记录时,它会抛出以下错误:panic: runtime error: invalid memory address or nil pointer dereference

有人可以帮助我弄清楚发生了什么以及如何解决吗?

英文:

I am consuming a REST API that returns XML and am trying to Unmarshal the XML and am having issues that appear that the omitempty is not working. Here is an example of a working XML file:

&lt;?xml version=&#39;1.0&#39; encoding=&#39;UTF-8&#39;?&gt;
&lt;customer uri=&quot;/api/customers/339/&quot; id=&quot;339&quot;&gt;
    &lt;name&gt;
    	&lt;first&gt;Firstname&lt;/first&gt;
    	&lt;last&gt;Lastname&lt;/last&gt;
	&lt;/name&gt;
    &lt;email&gt;myemail@example.com&lt;/email&gt;
    &lt;billing&gt;
    	&lt;address&gt;
    		&lt;address1&gt;123 Main St.&lt;/address123&gt;
    		&lt;address2&gt;&lt;/address2&gt;
    		&lt;city&gt;Nowhere&lt;/city&gt;
    		&lt;state&gt;IA&lt;/state&gt;
    		&lt;country&gt;USA&lt;/country&gt;
    		&lt;zip&gt;12345&lt;/zip&gt;
    	&lt;/address&gt;
	&lt;/billing&gt;
&lt;/customer&gt;

Here is an example of a "bad" record

&lt;?xml version=&#39;1.0&#39; encoding=&#39;UTF-8&#39;?&gt;
&lt;customer uri=&quot;/api/customers/6848/&quot; id=&quot;6848&quot;&gt;
    &lt;name&gt;
    	&lt;first&gt;Firstname&lt;/first&gt;
    	&lt;last&gt;Lastname&lt;/last&gt;
	&lt;/name&gt;
    &lt;email/&gt;
    &lt;billing/&gt;
&lt;/customer&gt;

Now I have my structs set up like the following:

 type Customer struct {
     ID      int      `xml:&quot;id,attr&quot;`
     Name    *Name    `xml:&quot;name,omitempty&quot;`
     Billing *Billing `xml:&quot;billing,omitempty&quot;`
 }

 type Billing struct {
     Address *Address `xml:&quot;address,omitempty&quot;`
 }

 type Address struct {
     address_1 string `xml:&quot;,omitempty&quot;`
     address_2 string `xml:&quot;,omitempty&quot;`
     city      string `xml:&quot;,omitempty&quot;`
     postal    string `xml:&quot;,omitempty&quot;`
     country   string `xml:&quot;,omitempty&quot;`
 }

 type Name struct {
     first, last string
 }

Reading through all of the records it works when the XML follows the pattern of the first example &lt;billing&gt;&lt;/billing&gt; but when it hits a record that has something like &lt;billing/&gt; it throws the following error: panic: runtime error: invalid memory address or nil pointer dereference

Can someone help me figure out what's going on and how to resolve it?

答案1

得分: 2

你可能误解了omitempty的含义。它只在数据进行编组(marshalling)时生效。如果你将<billing/>反编组到一个带有,omitempty的指针字段上,它仍然会初始化该字段。然后,由于XML元素为空,Billing本身的字段将不会被设置。实际上,如果你假设customer.Billing != nil意味着customer.Billing.Address != nil,你将会遇到观察到的恐慌。

注意:http://play.golang.org/p/dClkfOVLXh

英文:

You're probably misunderstanding what ,omitempty means. It takes effect when marshalling data, only. If you unmarshal &lt;billing/&gt; onto a pointer field with ,omitempty, it will still initialize the field. Then, since the XML element is empty, the fields of Billing itself won't be set. In practice, if you assume that customer.Billing != nil means customer.Billing.Address != nil, you'll get the observed panic.

Note: http://play.golang.org/p/dClkfOVLXh

huangapple
  • 本文由 发表于 2013年8月23日 12:52:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/18394911.html
匿名

发表评论

匿名网友

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

确定