随着 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(),忽略这个字段就行。
|  |      1Reficul      2019-10-11 11:05:01 +08:00 诶,辣么要是这个字段的值就是 0 咋办: 即预期希望输出  {"Y":0}。  如果 JSON 标准库加上这个 feature,是不是会破坏已有的兼容,应该这样的改动不会进吧。 所以。。。。老老实实使用指针吧。。。。 | 
|  |      2guonaihong OP @Reficul 未来 go 如果通过这个 feature。可以通过 omitempty 字段控制,加了才忽略。用指针还要判断指针为空的情况,用起来还是挺累的。 if p == nil { return } | 
|  |      3Reficul      2019-10-11 12:57:59 +08:00 @guonaihong  Y= nil 的时候忽略,和 Y = 0 (默认值)的时候忽略是不一样的呀。 比如你输出的这个 JSON 里希望这个值在某种场景下是不返回的,则忽略;但是在某种场景下需要返回,但是值就是 0 则不希望忽略。 | 
|  |      4guonaihong OP @Reficul  恩,这个需求只能用指针。 |