Golang中omitempty關鍵字的具體實現
用法
熟悉 Golang 的朋友對于 json 和 struct 之間的轉換一定不陌生,為了將代碼中的結構體與 json 數據解耦,通常我們會在結構體的 field 類型后加上解釋說明,例如在表示一個地址的時候, json 數據如下所示
{
"street": "200 Larkin St",
"city": "San Francisco",
"state": "CA",
"zipcode": "94102"
}
與之相對應的 Golang 結構體表示可能是這個樣子的
type address struct {
Street string `json:"street"` // 街道
Ste string `json:"suite"` // 單元(可以不存在)
City string `json:"city"` // 城市
State string `json:"state"` // 州/省
Zipcode string `json:"zipcode"` // 郵編
}
這樣無論代碼中的變量如何改變,我們都能成功將 json 數據解析出來,獲得正確的街道,城市等信息,到目前為止一切正常。但如果我們想要將地址結構體恢復成 json 格式時,問題就來了。比方說我們用下面這段代碼讀取了地址 json ,然后根據業(yè)務邏輯處理了之后恢復成正常的 json 打印出來
func main() {
? ? ? ? data := `{
? ? ? ? "street": "200 Larkin St",
? ? ? ? "city": "San Francisco",
? ? ? ? "state": "CA",
? ? ? ? "zipcode": "94102"
? ? }`
? ? addr := new(address)
? ? json.Unmarshal([]byte(data), &addr)
? ? ? ? // 處理了一番 addr 變量...
? ? addressBytes, _ := json.MarshalIndent(addr, "", " ? ?")
? ? fmt.Printf("%s\n", string(addressBytes))
}這段代碼的輸出是
{
"street": "200 Larkin St",
"suite": "",
"city": "San Francisco",
"state": "CA",
"zipcode": "94102"
}
多了一行 "suite": "", ,而這則信息在原本的 json 數據中是沒有的(在美國的地址中,如果不是群租公寓或者共享辦公樓, suite 這一條不存在很正常,人們直接用街道門牌號來表示地址就足夠了),但我們更希望的是,在一個地址有 suite 號碼的時候輸出,不存在 suite 的時候就不輸出,幸運的是,我們可以在 Golang 的結構體定義中添加 omitempty 關鍵字,來表示這條信息如果沒有提供,在序列化成 json 的時候就不要包含其默認值。稍作修改,地址結構體就變成了
type address struct {
Street string `json:"street"`
Ste string `json:"suite,omitempty"`
City string `json:"city"`
State string `json:"state"`
Zipcode string `json:"zipcode"`
}
重新運行,即可得到正確的結果。
陷阱
帶來方便的同時,使用 omitempty 也有些小陷阱,一個是該關鍵字無法忽略掉嵌套結構體。還是拿地址類型說事,這回我們想要往地址結構體中加一個新 field 來表示經緯度,如果沒有缺乏相關的數據,暫時可以忽略。新的 struct 定義如下所示
type address struct {
? ? Street ? ? string ? ? `json:"street"`
? ? Ste ? ? ? ?string ? ? `json:"suite,omitempty"`
? ? City ? ? ? string ? ? `json:"city"`
? ? State ? ? ?string ? ? `json:"state"`
? ? Zipcode ? ?string ? ? `json:"zipcode"`
? ? Coordinate coordinate `json:"coordinate,omitempty"`
}
type coordinate struct {
? ? Lat float64 `json:"latitude"`
? ? Lng float64 `json:"longitude"`
}讀入原來的地址數據,處理后序列化輸出,我們就會發(fā)現即使加上了 omitempty 關鍵字,輸出的 json 還是帶上了一個空的坐標信息
{
"street": "200 Larkin St",
"city": "San Francisco",
"state": "CA",
"zipcode": "94102",
"coordinate": {
"latitude": 0,
"longitude": 0
}
}
為了達到我們想要的效果,可以把坐標定義為指針類型,這樣 Golang 就能知道一個指針的“空值”是多少了,否則面對一個我們自定義的結構, Golang 是猜不出我們想要的空值的。于是有了如下的結構體定義
type address struct {
? ? Street ? ? string ? ? ?`json:"street"`
? ? Ste ? ? ? ?string ? ? ?`json:"suite,omitempty"`
? ? City ? ? ? string ? ? ?`json:"city"`
? ? State ? ? ?string ? ? ?`json:"state"`
? ? Zipcode ? ?string ? ? ?`json:"zipcode"`
? ? Coordinate *coordinate `json:"coordinate,omitempty"`
}
type coordinate struct {
? ? Lat float64 `json:"latitude"`
? ? Lng float64 `json:"longitude"`
}相應的輸出為
{
"street": "200 Larkin St",
"city": "San Francisco",
"state": "CA",
"zipcode": "94102"
}
另一個“陷阱”是,對于用 omitempty 定義的 field ,如果給它賦的值恰好等于默認空值的話,在轉為 json 之后也不會輸出這個 field 。比如說上面定義的經緯度坐標結構體,如果我們將經緯度兩個 field 都加上 omitempty
type coordinate struct {
Lat float64 `json:"latitude,omitempty"`
Lng float64 `json:"longitude,omitempty"`
}
然后我們對非洲幾內亞灣的“原點坐標”非常感興趣,于是編寫了如下代碼
func main() {
? ? cData := `{
? ? ? ? "latitude": 0.0,
? ? ? ? "longitude": 0.0
? ? }`
? ? c := new(coordinate)
? ? json.Unmarshal([]byte(cData), &c)
? ? ? ? // 具體處理邏輯...
? ? coordinateBytes, _ := json.MarshalIndent(c, "", " ? ?")
? ? fmt.Printf("%s\n", string(coordinateBytes))
}最終我們得到了一個
{}
這個坐標消失不見了!但我們的設想是,如果一個地點沒有經緯度信息,則懸空,這沒有問題,但對于“原點坐標”,我們在確切知道它的經緯度的情況下,(0.0, 0.0)仍然被忽略了。正確的寫法也是將結構體內的定義改為指針
type coordinate struct {
? ? Lat *float64 `json:"latitude,omitempty"`
? ? Lng *float64 `json:"longitude,omitempty"`
}這樣空值就從 float64 的 0.0 變?yōu)榱酥羔橆愋偷?nil ,我們就能看到正確的經緯度輸出。
{
"latitude": 0,
"longitude": 0
}
P.S. 本文中拿來作示例的地址是舊金山亞洲藝術博物館的地址,藏品豐富,上到夏商周,下至明清的文物都能看到,幾年前第一次去參觀,很是喜歡,印象深刻。
到此這篇關于Golang中omitempty關鍵字的具體實現的文章就介紹到這了,更多相關Golang omitempty 內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Go?處理大數組使用?for?range?和?for?循環(huán)的區(qū)別
這篇文章主要介紹了Go處理大數組使用for?range和for循環(huán)的區(qū)別,對于遍歷大數組而言,for循環(huán)能比for?range循環(huán)更高效與穩(wěn)定,這一點在數組元素為結構體類型更加明顯,下文具體分析感興趣得小伙伴可以參考一下2022-05-05
Go Uber靜態(tài)分析工具NilAway使用初體驗
這篇文章主要介紹了Go Uber靜態(tài)分析工具NilAway使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2024-01-01

