[toc]
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":"左右逢源"}
5. 参考
相关文章推荐
- CAF(C++ actor framework)(序列化之结构体,任意嵌套STL)(一)
- Go结构体嵌套
- Go进阶(7): JSON 序列化和反序列化
- fastjson和gson反序列化时的嵌套集合和抽象类处理
- go结构体
- go结构体转换
- 多层嵌套对象无法使用gson反序列化的问题The JsonDeserializer com.google.gson.DefaultTypeAdapters$CollectionTypeAdapter@3bf13cde failed to de
- go语言初始化内部结构体3中方式
- 数据结构(Data structures)(三):结构体嵌套
- Go 语言编程 — 高级数据类型 — 结构体
- 结构体的嵌套与返回
- Go语言结构体与二进制数组转换
- 扑克牌的嵌套结构体与相关的基础发牌杂谈
- go操作json,注意json的嵌套、数组
- Go语言中结构体方法副本传参与指针传参的区别介绍
- go语言之行--文件操作、命令行参数、序列化与反序列化详解
- Go 结构体、数组、字典和 json 字符串的相互转换方法
- Go-常识补充-切片-map(类似字典)-字符串-指针-结构体
- Go语言结构体定义和使用方法
- Go语言中结构体的使用-第1部分结构体