在Go中取消组合时键入checking json值



我使用的API通常提供json字符串值,但有时会提供数字。例如,99%的时间是这样的:

{
"Description": "Doorknob",
"Amount": "3.25"
}

但无论出于什么原因,有时都是这样的:

{
"Description": "Lightbulb",
"Amount": 4.70
}

这是我正在使用的结构,它在99%的时间内都能工作:

type Cart struct {
Description string `json:"Description"`
Amount      string `json:"Amount"`
}

但当他们提供数字金额时,它就会中断。取消组织结构时,类型检查的最佳方式是什么?

游乐场:https://play.golang.org/p/S_gp2sQC5-A

对于一般情况,您可以使用Burak Serdar的答案中所述的interface{}

具体来说,对于数字,有一种json.Number类型:它接受JSON数字和JSON字符串,并且它可以"自动地";如果数字是以Number.Int64()Number.Float64()的字符串形式给出的,则解析该数字。不需要自定义封送拆收器/解封拆收器。

type Cart struct {
Description string      `json:"Description"`
Amount      json.Number `json:"Amount"`
}

测试:

var (
cart1 = []byte(`{
"Description": "Doorknob",
"Amount": "3.25"
}`)
cart2 = []byte(`{
"Description": "Lightbulb",
"Amount": 4.70
}`)
)
func main() {
var c1, c2 Cart
if err := json.Unmarshal(cart1, &c1); err != nil {
panic(err)
}
fmt.Printf("%+vn", c1)
if err := json.Unmarshal(cart2, &c2); err != nil {
panic(err)
}
fmt.Printf("%+vn", c2)
}

输出(在Go Playground上尝试(:

{Description:Doorknob Amount:3.25}
{Description:Lightbulb Amount:4.70}

如果该字段可以是字符串或int,则可以使用接口{},然后计算出底层值:

type Cart struct {
Description string `json:"Description"`
Amount      interface{} `json:"Amount"`
}
func (c Cart) GetAmount() (float64,error) {
if d, ok:=c.Amount.(float64); ok {
return d,nil
}
if s, ok:=c.Amount.(string); ok {
return strconv.ParseFloat(s,64)
}
return 0, errors.New("Invalid amount")
}

最新更新