站長資訊網(wǎng)
        最全最豐富的資訊網(wǎng)站

        Golang中使用JSON時區(qū)分空字段和未設(shè)置字段的方法

        下面由golang教程欄目給大家介紹Golang中使用JSON時區(qū)分空字段和未設(shè)置字段的方法,希望對需要的朋友有所幫助!

        Golang中使用JSON時區(qū)分空字段和未設(shè)置字段的方法

        幾周前, 我在使用 Golang 微服務(wù), 需要添加使用 JSON 數(shù)據(jù)的 CURP 操作的支持. 通常, 我會為實體創(chuàng)建一個結(jié)構(gòu)體, 該結(jié)構(gòu)體中定義了所有字段以及 'omitempty' 屬性, 如下所示

        type Article struct {    Id   string      `json:"id"`    Name string      `json:"name,omitempty"`    Desc string      `json:"desc,omitempty"` }

        問題

        但是這種表示形式帶來了嚴重的問題, 尤其對于 Update 或 Edit 操作而言.

        例如, 假設(shè)更新請求的 JSON 數(shù)據(jù)看起來像是這樣

        {"id":"1234","name":"xyz","desc":""}

        注意為空的 desc 字段. 現(xiàn)在讓我們來看看這段請求數(shù)據(jù)在 Go 中解封后是怎么樣的

        func Test_JSON1(t *testing.T) {             jsonData:=`{"id":"1234","name":"xyz","desc":""}`    req:=Article{}    _=json.Unmarshal([]byte(jsonData),&req)    fmt.Printf("%+v",req) }Output: === RUN   Test_JSON1 {Id:1234 Name:xyz Desc:}

        這里的描述是一個空字符串, 很明顯客戶端希望將 desc 設(shè)置為空字符串, 這是由我們的程序推斷出來的.

        但是, 如果客戶端不希望更改 Desc 的現(xiàn)有值, 在這種情況下, 再次發(fā)送一個描述字符串是不正確的, 因此請求的 JSON 數(shù)據(jù)可能看起來像是這樣

        {"id":"1234","name":"xyz"}

        我們解封到我們的結(jié)構(gòu)體中

        func Test_JSON2(t *testing.T) {             jsonData:=`{"id":"1234","name":"xyz"}`    req:=Article{}    _=json.Unmarshal([]byte(jsonData),&req)    fmt.Printf("%+v",req) }Output: === RUN   Test_JSON2 {Id:1234 Name:xyz Desc:}

        額, 仍然會將 Desc 作為空字符串獲取, 那么如何區(qū)分未設(shè)置字段和空字段

        簡答? 指針

        解決辦法

        受到一些現(xiàn)有 Golang 庫的啟發(fā), 如 go-github. 我們可以將結(jié)構(gòu)體字段更改為指針類型, 如下所示

        type Article struct {    Id    string      `json:"id"`    Name *string      `json:"name,omitempty"`    Desc *string      `json:"desc,omitempty"` }

        通過這樣做, 我們在字段中添加了額外的狀態(tài). 如果原始 JSON 中不存在該字段, 則結(jié)構(gòu)體字段將為空 (nil).

        另一方面, 如果該字段確實存在并且為空, 則指針不為空, 并且該字段包含空值.

        注意 – 我沒有將 'Id' 字段更改為指針類型, 因為它不具備空狀態(tài), id 是必需的, 類似數(shù)據(jù)庫中的 id.

        我們再嘗試一下.

        func Test_JSON_Empty(t *testing.T) {    jsonData := `{"id":"1234","name":"xyz","desc":""}`    req := Article{}    _ = json.Unmarshal([]byte(jsonData), &req)    fmt.Printf("%+vn", req)    fmt.Printf("%sn", *req.Name)    fmt.Printf("%sn", *req.Desc) } func Test_JSON_Nil(t *testing.T) {    jsonData := `{"id":"1234","name":"xyz"}`    req := Article{}    _ = json.Unmarshal([]byte(jsonData), &req)    fmt.Printf("%+vn", req)    fmt.Printf("%sn", *req.Name) }

        Output

        === RUN   Test_JSON_Empty {Id:1234 Name:0xc000088540 Desc:0xc000088550} Name: xyz Desc:  --- PASS: Test_JSON_Empty (0.00s)=== RUN   Test_JSON_Nil {Id:1234 Name:0xc00005c590 Desc:<nil>} Name: xyz --- PASS: Test_JSON_Nil (0.00s)

        第一種情況, 由于 desc 設(shè)置為空字符串, 因此我們在 Desc 獲得了一個非空指針并包含一個空字符串的值. 第二種情況, 該字段未設(shè)置, 我們得到了一個空字符串指針.

        因此我們能夠區(qū)分兩種更新. 這種方式不僅適用于字符串, 而且適用于其他的所有數(shù)據(jù)類型, 包括整型, 嵌套結(jié)構(gòu)體, 等.

        但是這種方法也存在一些問題.

        空安全性: 非指針數(shù)據(jù)類型具備固有的空安全性. 在 Golang 中這意味著字符串或整型永遠不能為空. 他們始終具備默認值. 但是如果定義了指針, 則這些數(shù)據(jù)類型在未手動設(shè)置的情況下默認為空. 因此, 嘗試在不驗證可空性的情況下訪問那些指針的數(shù)據(jù)可能會導(dǎo)致應(yīng)用程序崩潰.

        # 以下代碼將崩潰, 因為 desc 為空 func Test_JSON_Nil(t *testing.T) {    jsonData := `{"id":"1234","name":"xyz"}`    req := Article{}    _ = json.Unmarshal([]byte(jsonData), &req)    fmt.Printf("%+vn", req)    fmt.Printf("%sn", *req.Desc) }

        通過始終檢查空指針可以很容易的解決此問題, 但你的代碼可能會看起來會很啰嗦.

        可打印性: 如在基于指針的解決方案的輸出中你可能已經(jīng)注意到的問題, 不會打印指針的值. 二十打印了指針的十六進制值, 這在應(yīng)用程序中沒什么用. 這也可以通過重新使用 stringer 接口來克服.

        func (a *Article) String() string {    output:=fmt.Sprintf("Id: %s ",a.Id)    if a.Name!=nil{    output+=fmt.Sprintf("Name: '%s' ",*a.Name)    }    if u.Desc!=nil{    output+=fmt.Sprintf("Desc: '%s' ",u.Desc)    }    return output }

        附錄:

        • 解決上述問題的另一種方法是使用具有可為空類型的三方庫, 其類型可提供檢查是否為空的方法, 而無需關(guān)心指針.
        • github.com/guregu/null
        • github.com/google/go-github

        原文地址:https://medium.com/@arpitkh96/differentiate-between-empty-and-not-set-fields-with-json-in-golang-957bb2c5c065

        譯文地址:https://learnku.com/go/t/49332

        贊(0)
        分享到: 更多 (0)
        網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號
        主站蜘蛛池模板: 精品黑人一区二区三区| 国产A∨免费精品视频| 精品亚洲aⅴ在线观看| 久久国产精品成人免费 | 中文字幕久久精品| 99re热这里只有精品视频中文字幕 | 午夜成人精品福利网站在线观看| 国产精品无码午夜福利| 国产精品无码一区二区在线| 久久精品国产亚洲77777| 精品日本一区二区三区在线观看| 少妇人妻偷人精品无码视频| 国产精品毛片a∨一区二区三区| 久久99国产精品尤物| 国产农村妇女毛片精品久久| 国精品无码一区二区三区左线| 久久精品国产只有精品66| 国产精品偷伦视频观看免费| 日韩精品人妻av一区二区三区| 日本精品久久久中文字幕| 亚洲中文久久精品无码| 国内精品视频九九九九| 久久91精品国产91久久小草| 一本久久a久久精品亚洲| 国产精品自产拍在线18禁| 国产精品嫩草影院一二三区入口| 亚洲精品97久久中文字幕无码| 国产精品麻豆入口| 四虎在线精品视频一二区| 久久青青草原精品国产| 亚洲国产精品成人久久蜜臀| 韩国三级中文字幕hd久久精品 | 国产精品成人99久久久久91gav| 精品亚洲aⅴ在线观看| 亚洲精品无码久久久影院相关影片| 国产精品毛片a∨一区二区三区| 国产精品久久久久jk制服| 亚洲av永久无码精品秋霞电影影院| 国产亚洲精品影视在线产品| 91久久精品无码一区二区毛片| 国产亚洲福利精品一区|