随着 go1.13 发布,reflect 包里新加了 IsZero 函数。随着该函数的加入,可能会解决一个遗留问题。
go version go1.13.1 linux/amd64
在 json 编码里面,如果打上 omitempty,值为空是不会输出内容的
package main
import (
"fmt"
//"reflect"
"encoding/json"
"time"
)
type test struct {
Tm time.Time `json:"tm,omitempty"`
X int `json:"x,omitempty"`
Y int
}
func main() {
all, err := json.Marshal(test{})
fmt.Printf("%s, %v\n", all, err)
}
/*
输出 {"tm":"0001-01-01T00:00:00Z","Y":0}, <nil>
*/
这什么情况? omitempty 没用 难道对结构体使用没有作用,tm 里面竟然有东西?我们加个自定义结构体再看下(time.Time 的实现方式是结构体)。
package main
import (
"encoding/json"
"fmt"
//"reflect"
"time"
)
type mystruct struct {
I int `json:"i,omitempty"`
J int `json:"j,omitempty"`
}
type test struct {
Tm time.Time `json:"tm,omitempty"`
X int `json:"x,omitempty"`
Y int
M mystruct `json:"m,omitempty"`
}
func main() {
all, err := json.Marshal(test{})
fmt.Printf("%s, %v\n", all, err)
//fmt.Printf("%t\n", reflect.ValueOf(test{}).IsZero())
}
/*
{"tm":"0001-01-01T00:00:00Z","Y":0,"m":{}}, <nil>
*/
自定义结构体声明的 m 字段有值,在这个版本里面 omitempty 遇到结构体还是没起作用。
随着 Value.IsZero 的加入,在未来的 go 版本上面的问题有可能得到解决。打开上面代码的注释, 会发现 reflect.ValueOf(test{}).IsZero()输出为 true。在 json 编码器检测到 omitempty 字段,再调用下 reflect.ValueOf(xxx).IsZero(),忽略这个字段就行。
1
Reficul 2019-10-11 11:05:01 +08:00
诶,辣么要是这个字段的值就是 0 咋办: 即预期希望输出 {"Y":0}。
如果 JSON 标准库加上这个 feature,是不是会破坏已有的兼容,应该这样的改动不会进吧。 所以。。。。老老实实使用指针吧。。。。 |
2
guonaihong OP @Reficul 未来 go 如果通过这个 feature。可以通过 omitempty 字段控制,加了才忽略。用指针还要判断指针为空的情况,用起来还是挺累的。
if p == nil { return } |
3
Reficul 2019-10-11 12:57:59 +08:00
@guonaihong
Y= nil 的时候忽略,和 Y = 0 (默认值)的时候忽略是不一样的呀。 比如你输出的这个 JSON 里希望这个值在某种场景下是不返回的,则忽略;但是在某种场景下需要返回,但是值就是 0 则不希望忽略。 |
4
guonaihong OP @Reficul 恩,这个需求只能用指针。
|