我问的是关于Go的encoding/json
,但我想这也适用于将JSON blob映射到任何语言的对象的任何其他JSON库。
这是一个例子。如果您想使用goo.gl URL shortener API缩短网址,则会收到成功回复:
{
"kind": "urlshortener#url",
"id": "http://goo.gl/fbsS",
"longUrl": "http://www.google.com/"
}
或错误回复:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "required",
"message": "Required",
"locationType": "parameter",
"location": "resource.longUrl"
}
],
"code": 400,
"message": "Required"
}
}
是否有一种惯用的处理方式 - 一种可以遵循两种完全不同的模式的响应?
通常我会使用地图/列表来处理JSON;我知道Go中有可能。我可以解散map[string]interface{}
,然后检查地图是否有"error"
作为关键字。但是我认为我必须再次解码成一个合适的struct
。 (我错了吗?)
我正在做这样的事情。我对每种反应都有一种类型:
type successResponse struct {
Kind string
Id string
LongUrl string
}
type errorResponse struct {
Error struct {
Errors []struct {
Domain string
Reason string
Message string
LocationType string
Location string
}
Code int
Message string
}
}
解码看起来像这样:
s := new(successResponse)
err := json.Unmarshal(blob, s)
if err == nil {
// handle success
} else {
e := new(errorResponse)
err = json.Unmarshal(blob, e)
if err == nil {
// handle error response
} else {
// handle actual error
}
}
但这看起来有点难看。我该怎么做呢?
答案 0 :(得分:6)
由于json响应中的字段彼此不同,因此您可以创建一个具有所有字段的并集的结构。 json解码器将忽略json字符串中不存在的字段,您可以测试字段的存在以了解您要返回的响应类型。
答案 1 :(得分:6)
我也对此感到困惑,并认为我必须再次解码它。但是,你没有。您只需将接口{}数据类型转换为适当的结构。
例如,如果json包已将值放入通用interface{}
,则可以使用ErrorType
将其类型转换为error := val.(ErrorType)
。
如果要根据值的类型进行解析,可以在foo.(type)
语句中使用switch
来“做正确的事”。
我本周才学习Go,所以这不是最漂亮的代码,但geodns JSON configuration parsing中有一些例子。
答案 2 :(得分:5)
你试过Go-SimpleJSON吗?我认为这可能会解决您的问题。
答案 3 :(得分:3)
type Response struct {
Kind string
Id string
LongUrl string
Error struct {
Errors []struct {
Domain string
Reason string
Message string
LocationType string
Location string
}
Code int
Message string
}
}
s := Response{}
if err := json.Unmarshal(blob, &s); err == nil {
if s.Error == nil {
// success
} else {
// error
}
} else {
// something went wrong
}