请知悉:本文最近一次更新为 2年 前,文中内容可能已经过时。

有的时候我们初始化一个json字段,预期是如果没有传入这个值,则不给结构体对应属性赋值,这个时候就需要用到omitempty了。

示例代码:

type Dog struct {
Breed string
// 下面的第一个逗号是将name标签和omitempty标签分开
WeightKg int `json:",omitempty"`
}

现在,如果将 WeightKg 设置为它的默认值(int 类型为0) ,那么 JSON 对象将省略键本身。

如果一个字符串为空“”,或者一个指针为零,或者一个切片中没有任何元素,也会发生同样的情况。

尽管 结构体 struct 没有“空”值,但是 struct 的指针有,空值为 nil。

type Dog struct {
Breed string
WeightKg int
Size *dimension `json:",omitempty"`
}

func main() {
d := Dog{
Breed: "pug",
}
b, _ := json.Marshal(d)
fmt.Println(string(b))
}

指针类型,输出的结果为:

{"Breed":"pug","WeightKg":0}

非指针的情况下:

type dimension struct {
Height int
Width int
}

type Dog struct {
Breed string
WeightKg int
Size dimension `json:",omitempty"`
}

func main() {
d := Dog{
Breed: "pug",
}
b, _ := json.Marshal(d)
fmt.Println(string(b))

输出的结果为:

{"Breed":"pug","WeightKg":0,"Size":{"Height":0,"Width":0}}

有一个问题特别给我带来了很多麻烦,那就是如何区分默认值和零值。

例如,如果我们有一个描述一家餐馆的结构,其中一个属性是坐着的顾客人数:


type Restaurant struct {
NumberOfCustomers int `json:",omitempty"`
}

func main() {
d := Restaurant{
NumberOfCustomers: 0,
}
b, _ := json.Marshal(d)
fmt.Println(string(b))
}

运行以上代码将打印:

{}

在这种情况下,餐馆中的顾客人数实际上可以是0,我们希望在 JSON 对象中传递这一信息。同时,如果没有设置 NumberOfCustomer,我们希望省略密钥。

换句话说,我们不希望0是 NumberOfCustomer 的“空”值。

解决这个问题的一种方法是使用 int 指针:

type Restaurant struct {
NumberOfCustomers *int `json:",omitempty"`
}

现在这个空值是一个 nil 指针,它不同于0:

func main() {
d1 := Restaurant{}
b, _ := json.Marshal(d1)
fmt.Println(string(b))
//Prints: {}

n := 0
d2 := Restaurant{
NumberOfCustomers: &n,
}
b, _ = json.Marshal(d2)
fmt.Println(string(b))
//Prints: {"NumberOfCustomers":0}
}

何时使用“omitvoid”

虽然我们已经经历了 omitvoid 的使用,但是最重要的是要记住,应该尽量少使用它。如果使用 Go 应用程序生成的 JSON 对象的应用程序没有区分未定义键和零值键,那么就没有理由首先使用 omitvoid 标记。

如果您确实决定使用它,那么请确保 Go 的“空”定义与应用程序的“空”定义相匹配。


参考资料

Golang Omitempty Explained


如您从本文得到了有价值的信息或帮助,请考虑扫描文末二维码捐赠和鼓励。

尊重他人劳动成果。转载请务必附上原文链接,我将感激不尽。


与《Go语言 omitempty的释义》相关的博文:


留言

avatar
😀
😀😁😂😅😭🤭😋😘🤔😰😱🤪💪👍👎🤝🌹👌