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. 参考
- https://zhuanlan.zhihu.com/p/296248435
|
请发表评论