10

我问这个关于 Go 的问题encoding/json,但我想它也适用于任何其他将 JSON blob 映射到任何语言的对象的 JSON 库。

这是一个例子。如果您想使用goo.gl URL 缩短 API来缩短 URL ,您会得到一个成功的响应:

{
 "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 中是可能的。我可以解组到 amap[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
    }
}

但这似乎有点丑陋。我应该如何处理这个?

4

4 回答 4

6

由于您的 json 响应中的字段彼此不同,您只需创建一个包含所有字段并集的结构。json 解码器将忽略 json 字符串中不存在的字段,您可以测试字段的存在以了解您返回的响应类型。

于 2012-08-24T06:22:35.437 回答
6

我也对此感到困惑,并认为我必须再次对其进行解码。不过,你不知道。您只需要将 interface{} 数据类型转换为适当的结构。

例如,如果 json 包已将值放入泛型interface{}中,您可以将其类型转换为ErrorTypewith error := val.(ErrorType)

如果您根据值的类型进行解析,则可以foo.(type)在语句中使用“做正确的事情”。switch

我这周才开始学习 Go,所以它不是最漂亮的代码,但在geodns JSON 配置解析中有一些示例。

于 2012-08-26T08:02:26.403 回答
5

你试过Go-SimpleJSON吗?我认为这可能会解决您的问题。

于 2012-08-24T07:37:17.180 回答
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
}
于 2012-08-24T10:48:00.233 回答