1. 忽略某个字段
-
格式
// 使用json tag指定json序列化与反序列化时的行为 type Person struct { Name string `json:"name"` // 指定json序列化/反序列化时使用小写name Age int64 Weight float64 `json:"-"` // 指定json序列化/反序列化时忽略此字段 }
-
代码
package main import ( "encoding/json" "fmt" ) type Person struct { Name string `json:"name"` // 指定json序列化/反序列化时使用小写name Age int64 Weight float64 `json:"-"` // 指定json序列化/反序列化时忽略此字段 } func main() { person := Person{ Name: "Jack", Age: 29, Weight: 53.2, } p, err := json.Marshal(person) if err != nil { fmt.Printf("json.Marshal failed, err:%v\n", err) return } fmt.Printf("str:%s\n", p) }
-
输出
str:{"name":"Jack","Age":29}
2. 忽略空值字段
当 struct
中的字段没有值时,json.Marshal()
序列化的时候不会忽略这些字段,而是默认输出字段的类型零值(例如int和float类型零值是 0,string类型零值是"",对象类型零值是 nil)。
如果想要在序列序列化时忽略这些没有值的字段时,可以在对应字段添加omitempty tag
-
示例
package main import ( "encoding/json" "fmt" ) type User struct { Name string `json:"name"` Email string `json:"email"` Hobby []string `json:"hobby"` } func omitemptyDemo() { // 当 struct 中的字段没有值Email,Hobby 字段时 u1 := User{ Name: "Jack", } // struct -> json string b, err := json.Marshal(u1) if err != nil { fmt.Printf("json.Marshal failed, err:%v\n", err) return } fmt.Printf("str:%s\n", b) } func main() { omitemptyDemo() }
-
输出
// 结构体没有字段时,会使用结构体字段对应的类型默认值 str:{"name":"Jack","email":"","hobby":null}
3. 去掉结构体没有字段的值
如果想要在最终的序列化结果中去掉空值字段,可以像下面这样定义结构体:
在对应字段处使用 json, omitempty tag
格式忽略不存在的字段值
-
格式
// 在tag中添加omitempty忽略空值 // 注意这里 hobby,omitempty 合起来是json tag值,中间用英文逗号分隔 type User struct { Name string `json:"name"` Email string `json:"email,omitempty"` Hobby []string `json:"hobby,omitempty"` }
-
demo
package main import ( "encoding/json" "fmt" ) type User2 struct { Name string `json:"name"` Email string `json:"email,omitempty"` Hobby []string `json:"hobby,omitempty"` } func omitemptyDemo1() { // 当 struct 中的字段没有值Email,Hobby 字段时 u1 := User2{ Name: "Jack", } // struct -> json string b, err := json.Marshal(u1) if err != nil { fmt.Printf("json.Marshal failed, err:%v\n", err) return } fmt.Printf("str:%s\n", b) } func main() { omitemptyDemo1() }
-
输出
// 输出会将空值忽略掉 str:{"name":"Jack"} // 序列化结果中没有email和hobby字段
4. 忽略嵌套结构体空值字段
4.1 解套结构体解包序列化
所谓嵌套解包,就是将嵌套的字段以水平展开与原结构体字段合并成一个无嵌套的 json字符串
-
demo结构如下
type Profile struct { Website string `json:"site"` Slogan string `json:"slogan"` } type User struct { Name string `json:"name"` Email string `json:"email,omitempty"` Hobby []string `json:"hobby,omitempty"` Profile //匿名结构体继承 } # 嵌套结构体序列化 func nestedStructDemo() { // 实例化结构体,缺少嵌套结构体 Profile u1 := User{ Name: "左右逢源", Hobby: []string{"足球", "双色球"}, } // 将结构体序列化成 json字符串 b, err := json.Marshal(u1) if err != nil { fmt.Printf("json.Marshal failed, err:%v\n", err) return } fmt.Printf("str:%s\n", b) }
-
匿名嵌套
Profile
时序列化后的json串为单层的, 这种序列化会将 嵌套结构体 解包,如下str:{"name":"左右逢源","hobby":["足球","双色球"],"site":"","slogan":""}
4.2 想要变成嵌套的json串,需要改为具名嵌套或定义字段tag
-
上面的结果并不是我们想要的结果,我们想要的json格式应该如下
str:{"name":"左右逢源","hobby":["足球","双色球"],"profile":{"site":"","slogan":""}}
-
嵌套格式如下
type User struct { Name string `json:"name"` Email string `json:"email,omitempty"` Hobby []string `json:"hobby,omitempty"` Profile `json:"profile"` //嵌套结构体,加上tag } // str:{"name":"左右逢源","hobby":["足球","双色球"],"profile":{"site":"","slogan":""}}
4.3 嵌套结构体如果无值,将对应json字段忽略掉
-
有的时候我们想在序列化的时候,如果嵌套结构体没有值,那么序列化成json的字段时将该字段忽略掉,这样可以节省内存空间,同时对于api返回也可以防止不必要的返回
str:{"name":"左右逢源","hobby":["足球","双色球"]} // profile结构体为空时,将此字段忽略掉
-
格式如下
type User struct { Name string `json:"name"` Email string `json:"email,omitempty"` Hobby []string `json:"hobby,omitempty"` *Profile `json:"profile,omitempty"` // 使用结构体指针,同时tag加入 omitempty属性表示可以为空 }
4.4 不修改原结构体忽略空值字段
-
比如这样的场景, 用户在调用创建用户接口时,api返回调用结果,需要json序列化User,但是不想把密码也序列化,又不想修改User结构体,这个时就可以使用创建另外一个结构体PublicUser匿名嵌套原User,同时指定Password字段为匿名结构体指针类型,并添加omitemptytag,示例代码如下:
type User struct { Name string `json:"name"` Password string `json:"password"` } type PublicUser struct { *User // 匿名嵌套 // 这里相当于将原User结构体中的Password字段覆盖掉了,使用空结构体及tag omitempty强制忽略这个字段 Password *struct{} `json:"password,omitempty"` } func omitPasswordDemo() { u1 := User{ Name: "左右逢源", Password: "123456", } b, err := json.Marshal(PublicUser{User: &u1}) if err != nil { fmt.Printf("json.Marshal u1 failed, err:%v\n", err) return } fmt.Printf("str:%s\n", b) // str:{"name":"左右逢源"} }
-
输出的时候就只有 Name字段被序列化成了 json字符串
str:{"name":"左右逢源"}