Golang 的 “omitempty” 關(guān)鍵字略解

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ā)布

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末陆赋,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子嚷闭,更是在濱河造成了極大的恐慌攒岛,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件胞锰,死亡現(xiàn)場(chǎng)離奇詭異灾锯,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)嗅榕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)顺饮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)吵聪,“玉大人,你說(shuō)我怎么就攤上這事兼雄∫魇牛” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵赦肋,是天一觀的道長(zhǎng)块攒。 經(jīng)常有香客問(wèn)我,道長(zhǎng)佃乘,這世上最難降的妖魔是什么囱井? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮趣避,結(jié)果婚禮上庞呕,老公的妹妹穿的比我還像新娘。我一直安慰自己程帕,他們只是感情好千扶,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著骆捧,像睡著了一般澎羞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上敛苇,一...
    開(kāi)封第一講書(shū)人閱讀 51,146評(píng)論 1 297
  • 那天妆绞,我揣著相機(jī)與錄音,去河邊找鬼枫攀。 笑死括饶,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的来涨。 我是一名探鬼主播图焰,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蹦掐!你這毒婦竟也來(lái)了技羔?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤卧抗,失蹤者是張志新(化名)和其女友劉穎藤滥,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體社裆,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拙绊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片标沪。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡榄攀,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出金句,到底是詐尸還是另有隱情檩赢,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布趴梢,位于F島的核電站,受9級(jí)特大地震影響币他,放射性物質(zhì)發(fā)生泄漏坞靶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一蝴悉、第九天 我趴在偏房一處隱蔽的房頂上張望彰阴。 院中可真熱鬧,春花似錦拍冠、人聲如沸尿这。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)射众。三九已至,卻和暖如春晃财,著一層夾襖步出監(jiān)牢的瞬間叨橱,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工断盛, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留罗洗,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓钢猛,卻偏偏與公主長(zhǎng)得像伙菜,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子命迈,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容