json和struct轉(zhuǎn)換簡(jiǎn)單介紹
熟悉 Golang 的朋友對(duì)于 json 和 struct 之間的轉(zhuǎn)換一定不陌生嚷节,為了將代碼中的結(jié)構(gòu)體與 json 數(shù)據(jù)解耦蝠猬,通常我們會(huì)在結(jié)構(gòu)體的 field 類(lèi)型后加上解釋說(shuō)明,注意:結(jié)構(gòu)體的屬性首字母必須大寫(xiě)句携,否則json解析會(huì)不生效
type Person struct {
Name string `json:"json_key_name"`
Age int `json:"json_key_age"`
}
func main() {
Per := Person{
Name: "小飯",
Age: 18,
}
res, _ := json.Marshal(Per)
fmt.Println(string(res))
return
}
//輸出結(jié)果
{"json_key_name":"小飯","json_key_age":18}
結(jié)構(gòu)體只初始化部分變量
接下來(lái)我們看另外一種情況
p := Person{
Name: "小飯",
}
res, _ := json.Marshal(p)
fmt.Println(string(res))
如果我們?cè)诮Y(jié)構(gòu)體初始化的時(shí)候只初始化了其中一個(gè)字段Name宏怔,那么理論上來(lái)說(shuō)返回的json應(yīng)該是
{"Name":"小飯"}
但是我們實(shí)際運(yùn)行一下返回的結(jié)果卻是
{"Name":"小飯","Age":0}
這明顯是不符合我們的預(yù)期的鹃唯,因?yàn)锳ge字段是我們不需要的烈菌。
如何解決
接下來(lái)就輪到咱們今天的主角登場(chǎng)了阵幸,解決方式很簡(jiǎn)單,在后面加上omitempty即可
type Person struct {
Name string
Age int `json:",omitempty"`
}
func main() {
p := Person{
Name: "小飯",
}
res, _ := json.Marshal(p)
fmt.Println(string(res))
}
//輸出結(jié)果
{"Name":"小飯"}
結(jié)構(gòu)體的特殊情況
我們?cè)賮?lái)看下面的這個(gè)例子
type Person struct {
Name string
Age int
}
type Student struct {
Num int
Person Person `json:",omitempty"` //對(duì)結(jié)構(gòu)體person使用了omitempty
}
func main() {
Stu := Student{
Num: 5,
}
res, _ := json.Marshal(Stu)
fmt.Println(string(res))
}
我們對(duì)結(jié)構(gòu)體Person定義了omitempty,按理說(shuō)我們?cè)诔跏蓟臅r(shí)候并沒(méi)有初始化結(jié)構(gòu)體的任何屬性芽世,所以轉(zhuǎn)換成json之后的打印結(jié)果應(yīng)該是只有{"Num":5}的挚赊,但是我們實(shí)際運(yùn)行之后發(fā)現(xiàn)打印的結(jié)果卻是
{"Num":5,"Person":{"Name":"","Age":0}}
為什么omitempty對(duì)于結(jié)構(gòu)體類(lèi)型不生效了呢?這是因?yàn)榻Y(jié)構(gòu)體(上面例子的Person)不知道空值是什么济瓢,GO只知道簡(jiǎn)單結(jié)構(gòu)體例如int,string,pointer 這種類(lèi)型的空值荠割,為了不顯示我們沒(méi)有提供值的自定義結(jié)構(gòu)體,我們可以使用結(jié)構(gòu)體指針葬荷。
為什么用指針類(lèi)型就可以解決這個(gè)問(wèn)題涨共?因?yàn)?strong>指針是基本類(lèi)型,Golang知道他的空值是啥宠漩,所以就直接賦值為nil(指針類(lèi)型的空值)举反。
type Person struct {
Name string
Age int
}
type Student struct {
Num int
Person *Person `json:",omitempty"` //如果想要omitempty生效,必須是指針類(lèi)型
}
func main() {
Stu := Student{
Num: 5,
}
res, _ := json.Marshal(Stu)
fmt.Println(string(res))
}
//輸出結(jié)果
{"Num":5}
omitempty的一個(gè)大坑
我們接下來(lái)還是看例子
type Person struct {
Age int `json:",omitempty"`
}
func main() {
Per := Person{
Age: 0,
}
res, _ := json.Marshal(Per)
fmt.Println(string(res))
}
按照咱們的預(yù)期扒吁,應(yīng)該給輸出
{"Age":0}
對(duì)不對(duì)火鼻,但是咱們實(shí)際運(yùn)行以后輸出的卻是
{}
這明顯有問(wèn)題啊,咱們需要的是輸出的json字段雕崩,是必須有age魁索,而且值是0,現(xiàn)在什么都沒(méi)輸出明顯是有問(wèn)題的盼铁。因?yàn)镚olang把0當(dāng)成了零值粗蔚,所以跟沒(méi)有賦值是一樣的
如果想解決這種問(wèn)題一種方法是使用int指針,因?yàn)閕nt指針的空值為nil,當(dāng)我想輸出0的時(shí)候饶火,我傳進(jìn)去地址鹏控,地址肯定不是空值nil,這樣肯定會(huì)顯示出來(lái)0
type Person struct {
Age *int `json:",omitempty"`
}
func main() {
age := 0
Per := Person{
Age: &age,
}
res, _ := json.Marshal(Per)
fmt.Println(string(res))
}
總結(jié)
- omitempty只是在把結(jié)構(gòu)體轉(zhuǎn)換成json的過(guò)程中肤寝,只會(huì)影響json轉(zhuǎn)換后的結(jié)果当辐,并不是影響結(jié)構(gòu)體本身,所以結(jié)構(gòu)體的任何屬性設(shè)置了omitempty之后鲤看,都不影響其正常使用
- omitempty的作用簡(jiǎn)單來(lái)說(shuō)就是在結(jié)構(gòu)體轉(zhuǎn)換json的過(guò)程中缘揪,把沒(méi)有賦值的結(jié)構(gòu)體屬性不在json中輸出而已。
- omitempty只支持簡(jiǎn)單的數(shù)據(jù)類(lèi)型义桂,對(duì)結(jié)構(gòu)體的數(shù)據(jù)類(lèi)型是不生效的找筝,如果需要生效,只能用結(jié)構(gòu)體指針
- omitempty分不清楚0值慷吊,""值和未賦值呻征,如果給某個(gè)屬性賦值0或者"",并且想輸出罢浇,只能用指針類(lèi)型
本文由mdnice多平臺(tái)發(fā)布