在Go中解码变量模式JSON

Ism*_*awi 10 json go

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

这是一个例子.如果您想使用goo.gl URL缩短程序API缩短URL,则可以获得成功的响应:

{
 "kind": "urlshortener#url",
 "id": "http://goo.gl/fbsS",
 "longUrl": "http://www.google.com/"
}
Run Code Online (Sandbox Code Playgroud)

或错误响应:

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "required",
    "message": "Required",
    "locationType": "parameter",
    "location": "resource.longUrl"
   }
  ],
  "code": 400,
  "message": "Required"
 }
}
Run Code Online (Sandbox Code Playgroud)

有没有一种惯用的处理方式 - 一种可以遵循两种完全不同的模式的响应?

通常我使用地图/列表来处理JSON; 我知道Go中有可能.我可以解组到a 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
    }
}
Run Code Online (Sandbox Code Playgroud)

解码看起来像这样:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

但这看起来有点难看.我该怎么做呢?

Jer*_*all 6

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


Ask*_*sen 6

我也对此感到困惑,并认为我必须再次解码它.但是,你没有.您只需将接口{}数据类型转换为适当的结构即可.

例如,如果JSON包已经把值转换成通用的interface{},可以强制转换成ErrorTypeerror := val.(ErrorType).

如果要根据值的类型进行解析,则可以foo.(type)switch语句中使用"做正确的事".

我本周才学习Go,所以它不是最漂亮的代码,但是在geodns JSON配置解析中有一些例子.


小智 5

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