目錄
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":"左右逢源"}
