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

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

Golang Json 解碼驗證不會引發接口錯誤

Golang Json 解碼驗證不會引發接口錯誤

Go
拉風的咖菲貓 2023-02-14 15:27:50
我完全是 Golang 的菜鳥,非常感謝以下方面的任何幫助我有這段代碼片段,運行良好var settings CloudSettingstype CloudSettings struct {...    A1 *bool `json:"cloud.feature1,omitempty"`...}err = json.NewDecoder(request.Body).Decode(&settings)An attempt to send an invalid string would raise this error:curl ... -d '{"cloud.feature1" : "Junk"}'"message":"Error:strconv.ParseBool: parsing \"Junk\": invalid syntax Decoding request body."現在,我們有一個單獨的LocalSettings結構,同樣的功能需要有條件地處理云/本地設置解碼于是,代碼改為:var settings interface{} = CloudSettings{}// If the request header says local settingssettings = LocalSettings{}/* After this change Decode() no longer raises any error for invalid strings and accepts anything */err = json.NewDecoder(request.Body).Decode(&settings)所以問題是為什么我會看到這種行為,我將如何解決這個問題?如果我有 2 個單獨的settings變量,那么從那一點開始的整個代碼將只是重復,我想避免
查看完整描述

2 回答

?
SMILET

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

在第二個片段中,您有一個初始化為結構的接口,但傳遞了該接口的地址。該接口包含一個不能被覆蓋的LocalSettingsorCloudSetting值,因此解碼器創建一個map[string]interface{},將傳遞的接口的值設置為指向該值,然后解組數據。當您運行第二個代碼段時,您不會初始化本地設置或云設置。

改變:

settings=&CloudSettings{}

或者

settings=&LocalSettings{}

err = json.NewDecoder(request.Body).Decode(settings)

它應該表現得像預期的那樣


查看完整回答
反對 回復 2023-02-14
?
12345678_0001

TA貢獻1802條經驗 獲得超5個贊

根據您的問題,我假設所有字段(即使是具有相同名稱的字段)在 JSON 標記中都有一個cloud.或前綴。local.如果是這種情況,您可以簡單地將兩個選項嵌入到一個類型中:


type Wrapper struct {

    *CloudSettings

    *LocalSettings

}

然后解組到這個包裝器類型中。JSON 標簽將確保填充正確設置類型的正確字段:


wrapper := &Wrapper{}

if err := json.NewDecoder(request.Body).Decode(&wrapper); err != nil {

    // handle

}

// now to work out which settings were passed:

if wrapper.CloudSettings == nil {

    fmt.Println("Local settings provided!")

    // use wrapper.CloudSettings

} else {

    fmt.Println("Cloud settings provided!")

    // use wrapper.LocalSettings

}

您提到我們希望看到基于標頭值加載的本地設置。您可以簡單地解組有效負載,然后檢查標頭是否與加載的設置類型匹配。如果標頭指定本地設置,但有效負載包含云設置,則只需返回錯誤響應。


不過,我在這里假設您的 JSON 標簽對于兩種設置類型都是不同的。這并不總是適用,所以如果我的假設不正確,并且某些字段共享相同的 JSON 標簽,那么自定義 Unmarshal 函數將是可行的方法:


func (w *Wrapper) UnmarshalJSON(data []byte) error {

    // say we want to prioritise Local over cloud:

    l := LocalSettings{}

    if err := json.Unmarshal(data, &l); err == nil {

        // we could unmarshal into local without a hitch?

        w.CloudSettings = nil // ensure this is blanked out

        w.LocalSettings = &l // set local

        return nil

    }

    // we should use cloud settings

    c := CloudSettings{}

    if err := json.Unmarshal(data, &c); err != nil {

        return err

    }

    w.LocalSettings = nil

    w.CloudSettings = &c

    return nil

}

這樣,任何沖突都會得到處理,我們可以控制哪些設置優先。同樣,無論 JSON 解組的結果如何,您都可以簡單地交叉檢查標頭值 + 填充了哪種設置類型,然后從那里獲取它。


最后,如果兩種設置類型之間存在相當大的重疊,您也可以將有效負載解組為兩種類型,并在包裝類型中填充兩個字段:


func (w *Wrapper) UnmarshalJSON(data []byte) error {

    *w = Wrapper{} // make sure we start with a clean slate

    l := LocalSettings{}

    var localFail err

    if err := json.Unmarshal(data, &l); err == nil {

        w.LocalSettings = &l // set local

    } else {

        localFail = err

    }

    c := CloudSettings{}

    if err := json.Unmarshal(data, &c); err == nil {

        w.CloudSettings = &c

    } else if localFail != nil { // both unmarshal calls failed

        return err // maybe wrap/return custom error

    }

    return nil // one or more unmarshals were successful

}

這應該夠了吧


查看完整回答
反對 回復 2023-02-14
  • 2 回答
  • 0 關注
  • 161 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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