使用 go 的返回 json
数据的时候,go 默认会空值设置为默认值,但是在有些业务中不希望返回默认值,所以需要使用 omitempty
修饰从而忽略空值。不过 omitempty
的实际不能并不像你所想象那样,下面这些简单的程序片段用于测试 omitempty
的实际表现。
1. 基础数据结构
1.1 未采用 omitempty
Struct
type Student struct {
Id int `json:"id"`
Name string `json:"name"`
}
Input
Student{
Id: 1,
}
Result
{
"id": 1,
"name": ""
}
1.2 采用 omitempty
Struct
type Student struct {
Id int `json:"id,omitempty"`
Name string `json:"name,omitempty"`
}
Input
Student{
Id: 1
}
Result
{
"id": 1
}
1.3 当传入参数与默认值相同
Struct
type Student struct {
Id int `json:"id,omitempty"`
Name string `json:"name,omitempty"`
}
Input
Student{
Id: 0,
Name: "tom",
}
Result
{
"name": "tom"
}
第一个和第二个例子都非常符合预期,但是在第三种,明明给 id
赋值为 0,但是却没有输出结果。所以在使用 omitempty
的时候需要谨慎判断这个值在业务上是否可能为默认值,如果是要么不加上 omitempty
要么将这个值的类型设置为指针类型,否则在输出为 json 的时候就会丢失值。
2. 基础数据结构的指针类型
1.4 保持空值
Struct
type Student struct {
Id *int `json:"id,omitempty"`
Name string `json:"name,omitempty"`
}
Input
Student{
Name: "tom",
}
Resout
{
"name": "tom"
}
2.2. 设置值为默认值
Struct
type Student struct {
Id *int `json:"id,omitempty"`
Name string `json:"name,omitempty"`
}
Input
t := Student{}
t.Id = new(int)
*t.Id = 0
t.Name = "tome"
Result
{
"id": 0,
"name": "tome"
}
可以看到这里将 id
设置为指针类型之后即使传入的是 int
对应的默认值最后的结果还是有的,因为对于指针类型而言默认值为 nil
。这一点不仅可以用在处理输出数据上面还可以用在处理输入数据上面,比如上面那个数据结构,id = 0
是合法的,但是如果我们需要判断输入的参数中是否含有 id
这个字段,就可以将 id
设置为指针类型,如果表现为空指针则说明是没有输入这个字段。
3. 复合数据结构
3.1 复合类型的切片
Struct
type Class struct {
Teachers []Teacher `json:"teachers,omitempty"`
Students []Student `json:"students,omitempty"`
}
type Teacher struct {
Id int
Name string
}
type Student struct {
Id int `json:"id"`
Name string `json:"name"`
}
Input
class := Class{}
teacher := Teacher{
Id: 0,
Name: "joy",
}
class.Teachers = append(class.Teachers, teacher)
Result
{
"teachers": [
{
"Id": 0,
"Name": "joy"
}
]
}
可以看到对于复合类型的切片 omitempty
是可以生效的
3.2 复合数据类型
Struct
type Class struct {
MatheTeacher Teacher `json:"teachers,omitempty"`
Student Student `json:"students,omitempty"`
}
type Teacher struct {
Id int
Name string
}
type Student struct {
Id int `json:"id"`
Name string `json:"name"`
}
Input
class := Class{}
teacher := Teacher{
Id: 0,
Name: "joy",
}
class.MatheTeacher = teacher
Result
{
"teachers": {
"Id": 0,
"Name": "joy"
},
"students": {
"id": 0,
"name": ""
}
}
可以看到在这里普通的复合数据结构使用 omiempty
修饰并没有生效
3.3 复合数据结构的指针
Struct
type Class struct {
MatheTeacher *Teacher `json:"teachers,omitempty"`
Student *Student `json:"students,omitempty"`
}
Input
class := Class{}
teacher := Teacher{
Id: 0,
Name: "joy",
}
class.MatheTeacher = new(Teacher)
*class.MatheTeacher = teacher
Result
{
"teachers": {
"Id": 0,
"Name": "joy"
}
}
可以看到这里使用 omitempty
可以生效,需要注意的是这里的指针在赋值的时候必须先分配内存地址,否则就会出现空指针错误,并且不会在编译的时候报错,在生产环境中出现这种错误非常麻烦。