持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第20天,点击查看活动详情
Go omitepty 使用
开发过程中,往往会用到 json.Marshal和json.Unmarshal两个函数。
omitempty 在 json.Marshal 中可以赋予空值
使用
omitempty,如果选择使用了他,那你就要第一时间知道,各个值的空值是什么?
如果不使用 omitempty这个字段,会发生啥?
type PersonAllow struct {
Name string
Age int64
Birth time.Time
Children []PersonAllowEmpty
}
测试代码:
func TestMarshal_PersonAllow(t *testing.T) {
person := PersonAllow{}
jsonBytes := JsonMarshal(person)
fmt.Println(string(jsonBytes)) // {"Birth":"0001-01-01T00:00:00Z"}
}
执行结果:
=== RUN TestMarshal_PersonAllow
{"Name":"","Age":0,"Birth":"0001-01-01T00:00:00Z","Children":null}
--- PASS: TestMarshal_PersonAllow (0.00s)
PASS
如果加上 会怎么样?
type PersonAllowEmpty struct {
Name string `json:",omitempty"`
Age int64 `json:",omitempty"`
Birth time.Time `json:",omitempty"`
Children []PersonAllowEmpty `json:",omitempty"`
}
测试代码:
func TestMarshalEmpty2(t *testing.T) {
person := PersonAllowEmpty{}
jsonBytes := JsonMarshal(person)
fmt.Println(string(jsonBytes)) // {"Birth":"0001-01-01T00:00:00Z"}
}
执行结果:
=== RUN TestMarshalEmpty2
{"Birth":"0001-01-01T00:00:00Z"}
--- PASS: TestMarshalEmpty2 (0.00s)
PASS
坑
该关键字无法忽略掉嵌套结构体,当结构体相互嵌套的时候,那么omitempty就可能出现问题,比如:
type dimension struct {
Height int
Width int
}
type Dog struct {
Breed string
WeightKg int
Size dimension `json:",omitempty"`
}
func TestOmitmpty(t *testing.T) {
d := Dog{
Breed: "pug",
}
b, _ := json.Marshal(d)
fmt.Println(string(b))
}
执行结果:
=== RUN TestOmitmpty
{"Breed":"pug","WeightKg":0,"Size":{"Height":0,"Width":0}}
--- PASS: TestOmitmpty (0.00s)
PASS
可以看到 omitempty似乎没有生效,这是因为结构体dimension空值其实就是 dimension{} , 我们改成指针试试。
type dimension struct {
Height int
Width int
}
type Dog struct {
Breed string
WeightKg int
//Size dimension `json:",omitempty"`
Size *dimension `json:",omitempty"`
}
func TestOmitmpty(t *testing.T) {
d := Dog{
Breed: "pug",
}
b, _ := json.Marshal(d)
fmt.Println(string(b))
}
执行结果:
=== RUN TestOmitmpty
{"Breed":"pug","WeightKg":0}
--- PASS: TestOmitmpty (0.00s)
PASS
指针类型的空值为 nil, 直接赋值为nil(指针类型的空值)。
当我们的零值有特殊含义时,如果被忽略,会有问题, 比如经纬度 0,0 :
type coordinate struct {
Lat float64 `json:"latitude,omitempty"`
Lng float64 `json:"longitude,omitempty"`
}
func TestOmitmpty_1(t *testing.T) {
d := coordinate{
Lat: 0.0,
Lng: 0.0,
}
b, _ := json.Marshal(d)
fmt.Println(string(b))
}
执行结果:
=== RUN TestOmitmpty_1
{}
--- PASS: TestOmitmpty_1 (0.00s)
PASS
如何解决,使用指针
type coordinate struct {
Lat *float64 `json:"latitude,omitempty"`
Lng *float64 `json:"longitude,omitempty"`
}
func TestOmitmpty_1(t *testing.T) {
lat := 0.0
lng := 0.0
d := coordinate{
Lat: &lat,
Lng: &lng,
}
b, _ := json.Marshal(d)
fmt.Println(string(b))
}
执行结果:
=== RUN TestOmitmpty_1
{"latitude":0,"longitude":0}
--- PASS: TestOmitmpty_1 (0.00s)
PASS