有的时候我们初始化一个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 的“空”定义与应用程序的“空”定义相匹配。
参考资料
如您从本文得到了有价值的信息或帮助,请考虑扫描文末二维码捐赠和鼓励。
如本文对您有用,捐赠和留言 将是对我最好的支持~(捐赠可转为站内积分)
如愿意,请向朋友推荐本站,谢谢。
尊重他人劳动成果。转载请务必附上原文链接,我将感激不尽。