3 回答

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是一個相當已建立的產品)。

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"`

TA貢獻1873條經驗 獲得超9個贊
似乎這里提供了一個實現來解決這個問題,僅在 Go 中。
type account struct {
Name string
Balance int `json:",string"`
}
在我看來,更正確和可持續的方法是讓你用 JavaScript 之類的東西創建一個客戶端庫,然后將它發布到 NPM 注冊表中供其他人使用(私有存儲庫的工作方式相同)。通過提供這個庫,你可以以一種有意義的方式為消費者定制 API,并防止錯誤蔓延到你的主程序中。
- 3 回答
- 0 關注
- 218 瀏覽
添加回答
舉報