亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

解組 JSON 保留空值

解組 JSON 保留空值

Go
飲歌長嘯 2022-05-05 17:57:07
我的情況如下:我有一個用 Go 制作的服務器/工作者。在后臺例程中,服務器接收 JSON 格式的消息,然后使用此數據更新 MongoDB 數據庫。問題之一是,某些 MongoDB 數據類型,例如 ObjectId 和 Date,在必須表示為 JSON 時通常會轉換為字符串,因此在將該數據插入數據庫之前,我將 JSON 解組到一個結構中,并且然后將該結構發送到 MongoDB 驅動程序。該結構實現了 和 等方法UnmarshalJSON,MarshalBSONValue因此保留了它們的數據類型。太好了,一切都解決了。但是通過使用結構我遇到了另一個問題,假設我有以下結構:type Integers struct {    Foo *int `json:"foo" bson:"foo"`    Bar *int `json:"bar" bson:"foo"`    Baz *int `json:"baz" bson:"foo"`}然后我收到以下 JSON:{"foo": 0, "bar": null}有了這個 JSON,我應該用 , 和 ignore 更新我foo = 0的bar = null數據庫baz。但是,如果我在我的結構中解組這個 JSON,我將擁有相當于:Integers{    Foo: 1,    Bar: nil,    Baz: nil,}但是有了這個,我無法判斷我是否收到了barand baz,或者他們只是默認為nil,所以我無法正確更新數據庫。我如何相信它可以解決:通過具有以下結構:type Integers struct {    Foo SmartassInt `json:"foo,omitempty" bson:"foo,omitempty"`    Bar SmartassInt `json:"bar,omitempty" bson:"bar,omitempty"`    Baz SmartassInt `json:"baz,omitempty" bson:"baz,omitempty"`}我將能夠區分 anull和未收到的值,如下例所示:var foo int = 0var fooPointer *int = &foovar barPointer *int = nilintegers := Integers{    Foo: &fooPointer,    Bar: &barPointer,    Baz: nil,}使用這種結構,baz不會被插入到數據庫中,因為它的值是nil,并且nil由于 flag 被忽略omitempty。bar然而不是nil,但它指向nil,這與為空不同,因此它像null在數據庫中一樣正確插入。但是我怎樣才能用收到的 JSON 來實現這個初始化呢?標準 JSON 解組器會將bar和都初始化baz為nil.實現我自己的編組器方法,例如type NullableInt **intfunc (i NullableInt) MarshalJSON() ([]byte, error) {}func (i NullableInt) UnmarshalJSON(data []byte) error {}也不可能,因為NullableInt是指針,我無法在指針上實現方法。那么,我可以使用哪種方法來解決這個問題?
查看完整描述

1 回答

?
鳳凰求蠱

TA貢獻1825條經驗 獲得超4個贊

在解碼方面,您可以為自定義類型編寫自定義解組器:


type MaybeInt struct {

    Present bool

    Null    bool

    Value   int64

}


func (m *MaybeInt) UnmarshalJSON(data []byte) error {

    s := string(data)

    m.Present = true

    if s == "null" {

        m.Null = true

        return nil

    }

    v, err := strconv.ParseInt(s, 10, 64)

    m.Value = v

    return err

}

完整的例子在這里。不幸的是,這在編碼方面不起作用:MarshalJSON處理程序無法指示該字段為空。顯而易見的方法是nil, nil從 Marshaler 返回,但這不起作用。也不回[]byte{}, nil。


你可能會想:好吧,讓我們使用一個指針,并將它設置為nil當我們想說該字段應該被省略時。這適用于解碼端,但現在編碼端失敗了,因為編碼器看到文字null并且根本不調用我們的編碼器!


最終,我們可以將這兩種技術結合起來:讀入MaybeInt、編碼(寫入)*MaybeInt。我們需要并行結構類型。我們可以根據輸入類型設置輸出類型。我不認為這很漂亮,而且其中的reflect代碼很糟糕(你也可以看到我所有的調試痕跡),但這實際上似乎有效:Playground link。在實踐中reflect,您可能只為每個“可能”值的情況編寫一個函數,而不是使用 。


查看完整回答
反對 回復 2022-05-05
  • 1 回答
  • 0 關注
  • 179 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號