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

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

如何告訴客戶端他們需要從 Go 服務器發送一個整數而不是一個字符串?

如何告訴客戶端他們需要從 Go 服務器發送一個整數而不是一個字符串?

Go
皈依舞 2021-12-07 19:40:06
假設我在服務器上有以下 Go 結構type account struct {    Name    string    Balance int}我想對傳入的請求調用 json.Decode 以將其解析為帳戶。    var ac account    err := json.NewDecoder(r.Body).Decode(&ac)如果客戶端發送以下請求:{    "name": "[email protected]",     "balance": "3"}Decode() 將返回以下錯誤:json: cannot unmarshal string into Go value of type int現在可以將其解析為“您為 Balance 發送了一個字符串,但您確實應該發送一個整數”,但這很棘手,因為您不知道字段名稱。如果請求中有很多字段,它也會變得更加棘手 - 您不知道哪個解析失敗。對于請求中任意數量的整數字段,在 Go 中處理傳入請求并返回錯誤消息“余額必須是字符串”的最佳方法是什么?
查看完整描述

3 回答

?
慕工程0101907

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

您可以為“余額”字段使用帶有自定義解組算法的自定義類型。


現在有兩種可能:


處理兩種類型:


package main


import (

    "encoding/json"

    "fmt"

    "strconv"

)


type Int int


type account struct {

    Name    string

    Balance Int

}


func (i *Int) UnmarshalJSON(b []byte) (err error) {

    var s string

    err = json.Unmarshal(b, &s)

    if err == nil {

        var n int

        n, err = strconv.Atoi(s)

        if err != nil {

            return

        }

        *i = Int(n)

        return

    }


    var n int

    err = json.Unmarshal(b, &n)

    if err == nil {

        *i = Int(n)

    }

    return

}


func main() {

    for _, in := range [...]string{

        `{"Name": "foo", "Balance": 42}`,

        `{"Name": "foo", "Balance": "111"}`,

    } {

        var a account

        err := json.Unmarshal([]byte(in), &a)

        if err != nil {

            fmt.Printf("Error decoding JSON: %v\n", err)

        } else {

            fmt.Printf("Decoded OK: %v\n", a)

        }

    }

}

游樂場鏈接。


只處理一個數字類型,并通過一個合理的錯誤使其他任何事情失?。?/p>


package main


import (

    "encoding/json"

    "fmt"

)


type Int int


type account struct {

    Name    string

    Balance Int

}


type FormatError struct {

    Want   string

    Got    string

    Offset int64

}


func (fe *FormatError) Error() string {

    return fmt.Sprintf("Invalid data format at %d: want: %s, got: %s",

        fe.Offset, fe.Want, fe.Got)

}


func (i *Int) UnmarshalJSON(b []byte) (err error) {

    var n int

    err = json.Unmarshal(b, &n)

    if err == nil {

        *i = Int(n)

        return

    }

    if ute, ok := err.(*json.UnmarshalTypeError); ok {

        err = &FormatError{

            Want:   "number",

            Got:    ute.Value,

            Offset: ute.Offset,

        }

    }

    return

}


func main() {

    for _, in := range [...]string{

        `{"Name": "foo", "Balance": 42}`,

        `{"Name": "foo", "Balance": "111"}`,

    } {

        var a account

        err := json.Unmarshal([]byte(in), &a)

        if err != nil {

            fmt.Printf("Error decoding JSON: %#v\n", err)

            fmt.Printf("Error decoding JSON: %v\n", err)

        } else {

            fmt.Printf("Decoded OK: %v\n", a)

        }

    }

}

游樂場鏈接。


還有第三種可能性:為整個account類型編寫自定義解組器,但它需要更多涉及的代碼,因為您需要使用encoding/json.Decoder類型的方法實際迭代輸入 JSON 數據 。


看完你的


對于請求中任意數量的整數字段,在 Go 中處理傳入請求并返回錯誤消息“余額必須是字符串”的最佳方法是什么?


更仔細,我承認有整個類型的定制解析器唯一明智的可能性,除非你是一個OK第三方軟件包實現解析器通過JSON模式支持驗證(我想我會看看這個第一次作為juju是一個相當已建立的產品)。


查看完整回答
反對 回復 2021-12-07
?
慕姐4208626

TA貢獻1852條經驗 獲得超7個贊

對此的解決方案可能是使用類型斷言,通過使用映射將 JSON 數據解組為:


type account struct {

    Name    string

    Balance int

}


var str = `{

    "name": "[email protected]", 

    "balance": "3"

}`


func main() {

    var testing = map[string]interface{}{}

    err := json.Unmarshal([]byte(str), &testing)

    if err != nil {

        fmt.Println(err)

    }


    val, ok := testing["balance"]

    if !ok {

        fmt.Println("missing field balance")

        return

    }


    nv, ok := val.(float64)

    if !ok {

        fmt.Println("balance should be a number")

        return

    }


    fmt.Printf("%+v\n", nv)

}

見http://play.golang.org/p/iV7Qa1RrQZ


使用這里的類型斷言是float64因為它是 Go 的 JSON 解碼器支持的默認數字類型。


應該注意的是,這種使用interface{}可能不值得麻煩。


該UnmarshalTypeError(https://golang.org/pkg/encoding/json/#UnmarshalFieldError)包含一個Offset領域,可能允許檢索觸發錯誤的JSON數據的內容。


例如,您可以返回以下類型的消息:


cannot unmarshal string into Go value of type int near `"balance": "3"`


查看完整回答
反對 回復 2021-12-07
?
眼眸繁星

TA貢獻1873條經驗 獲得超9個贊

似乎這里提供了一個實現來解決這個問題,僅在 Go 中。


type account struct {

    Name    string

    Balance int `json:",string"`

}

在我看來,更正確和可持續的方法是讓你用 JavaScript 之類的東西創建一個客戶端庫,然后將它發布到 NPM 注冊表中供其他人使用(私有存儲庫的工作方式相同)。通過提供這個庫,你可以以一種有意義的方式為消費者定制 API,并防止錯誤蔓延到你的主程序中。


查看完整回答
反對 回復 2021-12-07
  • 3 回答
  • 0 關注
  • 218 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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