json.Unmarshal是否要求您的结果结构与传入的JSON完全匹配?

时间:2018-04-17 17:50:47

标签: json go

我想要解组的JSON字符串:

{
  "id":1720,
  "alertId":1,
  "alertName":"{stats} Test Lambda Alert",
  "dashboardId":5,
  "panelId":2,
  "userId":0,
  "newState":"alerting",
  "prevState":"ok",
  "time":1523983581000,
  "text":"",
  "regionId":0,
  "tags":[],
  "login":"",
  "email":"",
  "avatarUrl":"",
  "data":{
    "evalMatches":[
        {
         "metric":"{prod}{stats} Lambda Alert Test",
         "tags":null,
         "value":16.525333333333332
         }
     ]
   }
}

我通过请求获取原始流:bodyBytes, err := ioutil.ReadAll(resp.Body)

我希望我能指定一个能够提取我关注的值的结构,例如,

type Result struct {
    ID string `json:"id"`
    Time int64 `json:"time"`
}

然而,当我尝试这个时,我会遇到错误。

type Result struct {
    ID   string `json:"id"`
    Time string `json:"time"`
}

var result Result
err2 := json.Unmarshal(bodyBytes, &result)
if err2 != nil {
    log.Fatal(fmt.Sprintf(`Error Unmarshalling: %s`, err2))
}
fmt.Println(result.ID)
  

错误解组:json:无法将数组解组为类型为main.Result的Go值

我怀疑这个错误可能是由ioutil.ReadAll()实际返回的内容造成的,因为如果我执行[ ],它会在fmt.Println(string(bodyBytes))中包含上面的JSON字符串,但如果我尝试json.Unmarshal(bodyBytes[0], &result),我只是遇到编译错误,所以我不确定。

如果我要解组JSON字符串,是否必须在type Result struct中指定完整结构?有没有解决的办法?我不想被绑定到我收到的JSON对象(如果API在上游发生变化,它需要我们修改我们的代码以识别它等)。

1 个答案:

答案 0 :(得分:3)

您可以解组为仅表示JSON文档的某些字段的结构,但字段类型必须匹配,因为错误明确指出:

  

无法将数字解组为Go结构字段Result.id,类型为字符串

您无法将数字解组为字符串。如果您将ID字段定义为任何数字类型,它将正常工作:

package main

import (
    "encoding/json"
    "fmt"
)

var j = []byte(`
{
  "id":1720,
  "prevState":"ok",
  "time":1523983581000,
  "text":"",
  "regionId":0
}
`)

type Result struct {
    ID   int   `json:"id"` // or any other integer type, or float{32,64}, or json.Number
    Time int64 `json:"time"`
}

func main() {
    var r Result
    err := json.Unmarshal(j, &r)
    fmt.Println(r, err)
}

在操场上试试:https://play.golang.org/p/lqsQwLW2dHZ

<强>更新

您刚刚根据收到的实际错误编辑了问题。您必须将JSON数组解组为切片。因此,如果HTTP响应实际上返回一个JSON数组,则在[] Result:

中解组
var j = []byte(`
[
    {
      "id":1720,
      "prevState":"ok",
      "time":1523983581000,
      "text":"",
      "regionId":0
    }
]
`)

var r []Result
err := json.Unmarshal(j, &r)
fmt.Println(r[0], err)

https://play.golang.org/p/EbOVA8CbcFO

要生成与JSON文档匹配的Go类型,请使用https://mholt.github.io/json-to-go/