結構體的tag
tag是結構體的元信息,運行時通過反射機制讀取。結構體的tag一般定義在相應字段的後面,格式爲:
fieldName fieldType `key1:"value1" key2:"value2"
同一個結構體字段可以設置多個鍵值對tag,不同的鍵值對之間使用空格分隔。
json tag
默認情況下序列化與反序列化使用的都是結構體的原生字段名,可以通過給結構體字段添加json tag來指定序列化後的字段名。
例如代碼:
package main
import (
"fmt"
"encoding/json"
)
type Student struct {
Name string `json:"name"`
Age int64
Weight float64
Height float64
}
func main() {
s1 := Student{
Name: "jack",
Age: 20,
Weight: 71.5,
Height: 172.5,
}
b, err := json.Marshal(s1)
if err != nil {
fmt.Printf("json.Marshal failed, err:%v\n", err)
return
}
fmt.Printf("s1: %s\n", b)
var s2 Student
err = json.Unmarshal(b, &s2)
if err != nil {
fmt.Printf("json.Unmarshal failed, err:%v\n", err)
return
}
fmt.Printf("s2: %#v\n", s2)
}
輸出:
s1: {"name":"jack","Age":20,"Weight":71.5,"Height":172.5}
s2: main.Student{Name:"jack", Age:20, Weight:71.5, Height:172.5}
使用json tag序列化時忽略任一字段
使用“-”作爲相應字段json tag的value值,如:
type Student struct {
Name string `json:"name"`
Age int64
Weight float64 `json:"-"`
Height float64
}
輸出:
s1: {"name":"jack","Age":20,"Height":172.5}
s2: main.Student{Name:"jack", Age:20, Weight:0, Height:172.5}
注:反序列化時仍將恢復該字段,零值處理。
使用json tag序列化時忽略普通結構體中的爲空字段
使用“omitempty”作爲相應字段json tag的value值,注意此時在“omitempty”前一定指定一個字段名,否則“omitempty”將作爲字段名處理。如:
type Student struct {
Name string `json:"name"`
Age int64
Weight float64 `json:"weight,omitempty"`
Height float64
}
此時如果這樣初始化s1:
s1 := Student{
Name: "jack",
Age: 20,
Height: 172.5,
}
輸出:
s1: {"name":"jack","Age":20,"Height":172.5}
s2: main.Student{Name:"jack", Age:20, Weight:0, Height:172.5}
可見,空字段Weight在序列化時被忽略掉了。
如果這樣初始化s1:
s1 := Student{
Name: "jack",
Age: 20,
Weight: 0,
Height: 172.5,
}
輸出:
s1: {"name":"jack","Age":20,"Height":172.5}
s2: main.Student{Name:"jack", Age:20, Weight:0, Height:172.5}
可見,使用“omitempty”的字段爲零值時在序列化結果中也被忽略掉了。
使用json tag 忽略嵌套結構體中的爲空字段
由於具名嵌套結構體與匿名嵌套結構體在序列化後只存在是否攤平的區別,這裏不做細緻討論,使用匿名嵌套結構體(這裏注:若使用匿名嵌套結構體,但同時使用json tag爲該被嵌套結構體指定了字段名,序列化結果該被嵌套結構體不會被攤平)。
若要在被嵌套結構體中的某一字段爲空時使其在序列化結果中被忽略,操作方法與上方普通結構體中字段一致。
若要在被嵌套結構體整體爲空時使其在序列化結果中被忽略,不僅要在被嵌套結構體字段後加上json:"fileName,omitempty"
,還要將其改爲結構體指針。如:
type BodyInfo struct {
Weight float64
Height float64
}
type Student struct {
Name string `json:"name"`
Age int64
*BodyInfo `json:"bodyinfo,omitempty"`
}
此時s1爲:
s1 := Student{
Name: "jack",
Age: 20,
}
輸出:
s1: {"name":"jack","Age":20}
s2: main.Student{Name:"jack", Age:20, BodyInfo:(*main.BodyInfo)(nil)}
不修改原結構體忽略某字段
需要創建另外一個結構體來匿名嵌套原結構體,同時指定待忽略字段爲匿名結構體指針類型,並添加omitempty的json tag。如:
package main
import (
"fmt"
"encoding/json"
)
type Student struct {
Name string `json:"name"`
Age int64 `json:"age"`
Weight float64
Height float64
}
type PStudent struct {
*Student
Age *struct{} `json:"age,omitempty"`
}
func main() {
s1 := Student{
Name: "jack",
Age: 20,
Weight: 61.5,
Height: 172.5,
}
ps1 := PStudent{
Student: &s1,
}
b, err := json.Marshal(ps1)
if err != nil {
fmt.Printf("json.Marshal failed, err:%v\n", err)
return
}
fmt.Printf("s1: %s\n", b)
var s2 PStudent
err = json.Unmarshal(b, &s2)
if err != nil {
fmt.Printf("json.Unmarshal failed, err:%v\n", err)
return
}
fmt.Printf("s2.student: %#v s2.age: %v\n", *s2.Student, s2.Age)
}
輸出:
s1: {"name":"jack","Weight":61.5,"Height":172.5}
s2.student: main.Student{Name:"jack", Age:0, Weight:61.5, Height:172.5} s2.age: <nil>