xml - `,omitempty`和Go 's standard ` xml`包中的指针字段

标签 xml go pointers

将结构体的 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
}

https://play.golang.org/p/C2fuBfv69Ny

关于xml - `,omitempty`和Go 's standard ` xml`包中的指针字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68327573/

相关文章:

python - 如何读取plist中的响应字符串?

go - 执行命令时如何使用文件作为标准输入

concurrency - 相同的 Golang 代码不同的输出,为什么?

C#引用成员变量

c - (*exptr)->cnt 与 exptr->cnt 或 (*exptr).cnt 相同吗?

javascript - 有什么办法可以在从js生成的excel文件上设置安全内容吗?

android - 以编程方式创建带圆角的图层列表

xml - 是否可以在 Jenkins 测试作业中下载原始 xml 文件

go - 使用模块时如何让 Travis 更快地构建

c - 在 C 中用两个字符串初始化一个 const char * const *