将结构体的 bool 字段编码为 XML 时,,omitempty
选项对于大多数用途而言并不是很有用 - false
是 Go 中 bool 变量的零值并且,正如预期的那样,编码时将忽略值为 false 的 bool ,omitempty
字段。最常建议的解决方案似乎是使用指针,它可以指示值是否存在。这是我对这个想法的基本实现:
package main
import (
"encoding/xml"
"fmt"
)
type Person struct {
XMLName xml.Name `xml:"person"`
IsMarried *bool `xml:"married"` // Required field.
IsRetired *bool `xml:"retired,omitempty"` // Optional field.
}
func boolPointer(b bool) *bool {
return &b
}
func printPersonXml(person Person) {
output, err := xml.MarshalIndent(person, " ", " ")
if err != nil {
fmt.Printf("error: %v\n", err)
} else {
fmt.Println(string(output))
}
}
func main() {
person := Person{
IsMarried: boolPointer(true),
IsRetired: nil,
}
printPersonXml(person)
}
这按预期工作并产生输出
<person>
<married>true</married>
</person>
但是,似乎在这种情况下 ,omitempty
选项完全失去了意义。任何具有 nil
值的字段都不会包含在生成的 XML 代码中。例如,如果我将 main()
的内容更改为
person := Person{
IsMarried: nil,
IsRetired: nil,
}
printPersonXml(person)
输出变为
<person></person>
尽管我更愿意
<person>
<married></married>
</person>
如上所述here ,这可能是预期的行为:“Marshal 通过编码指针所指向的值来处理指针,或者如果指针为零,则不写入任何内容。”
但是,是否可以使用标准 xml
包实现我喜欢的行为?如果是,是否需要为其引入新类型和自定义 MarshalXML()
方法?
尽管出于显而易见的原因,我在这里重点关注 bool 变量,但我也想将这种方法扩展到其他基本类型的指针。
最佳答案
“是否可以使用标准 xml 包实现我喜欢的行为?如果可以,是否需要为其引入新类型和自定义 MarshalXML() 方法?” -- 是的,并且是的。
例如:
type Bool struct {
Bool bool
IsValid bool
}
func (b Bool) MarshalXML(e *xml.Encoder, se xml.StartElement) error {
if b.IsValid {
return e.EncodeElement(b.Bool, se)
}
return e.EncodeElement("", se)
}
type OptionalBool struct {
Bool bool
IsValid bool
}
func (b OptionalBool) MarshalXML(e *xml.Encoder, se xml.StartElement) error {
if b.IsValid {
return e.EncodeElement(b.Bool, se)
}
return nil
}
关于xml - `,omitempty`和Go 's standard ` xml`包中的指针字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68327573/