我有一个想要解组的 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 类型的 Go 值。结果
我怀疑此错误可能是由于实际从ioutil.ReadAll()
返回的内容,因为如果我执行fmt.Println(string(bodyBytes))
,它将上述 JSON 字符串包装在[ ]
中,但如果我尝试json.Unmarshal(bodyBytes[0], &result)
,我只是得到编译错误,所以我不确定。
如果我想取消封送 JSON 字符串,我是否必须在type Result struct
中指定完整的结构?有没有办法解决这个问题?我不想绑定到我收到的 JSON 对象(如果 API 在上游发生变化,它需要我们修改代码以识别它,等等(。
您可以取消编组为仅表示 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/。