
go语言中解析顶层json数组时,需直接使用切片类型而非嵌套结构体,否则会因类型不匹配导致“cannot unmarshal array into go value”错误。
go语言中解析顶层json数组时,需直接使用切片类型而非嵌套结构体,否则会因类型不匹配导致“cannot unmarshal array into go value”错误。
在Go中进行JSON反序列化时,Go结构体的字段必须与JSON数据的层级结构严格对应。你提供的原始JSON是:
[{
"name": "rdj",
"place": "meh",
"meh": ["bow", "blah"]
}]
这是一个顶层JSON数组([]),其元素是对象({}),而非键值对形式的JSON对象(如 {"A": [...]})。但你的结构体定义却是:
type first struct {
A []one
}
这表示你期望解析的是形如 {"A": [...]} 的JSON——即一个包含字段 A 的对象,而 A 的值才是数组。当 json.Unmarshal 或 Decoder.Decode 遇到顶层数组却传入 *first 类型指针时,Go会尝试将整个数组赋给 first 类型变量,自然报错:
panic: json: cannot unmarshal array into Go value of type main.first
✅ 正确做法是:让Go变量类型与JSON实际结构完全一致。
由于JSON是 []T(数组),就应声明为 []T 类型的变量:
type One struct { // 建议首字母大写,符合Go导出规范
Name string `json:"name"`
Place string `json:"place"`
Meh []string `json:"meh"` // 若需读取 "meh" 字段,必须显式声明
}
func main() {
res, err := http.Get("http://127.0.0.1:8080/sample/")
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
var data []One // ← 直接声明为切片,匹配顶层JSON数组
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
log.Fatal("JSON decode error:", err)
}
fmt.Printf("%+v\n", data)
// 输出:[{Name:"rdj" Place:"meh" Meh:["bow" "blah"]}]
}
⚠️ 注意事项:
- JSON tag 中的冒号后不能有空格:
json: "place"是错误的,应为json:"place"(否则tag失效,字段无法绑定); - 若JSON中存在未定义字段(如
"meh"),又希望保留其值,可添加json:"-"忽略,或用map[string]interface{}+ 手动提取,但最佳实践是在结构体中显式声明所需字段; - 使用
http.Get后务必检查err,避免nilresponse 导致 panic; -
defer res.Body.Close()应在检查err后立即放置,确保资源释放。
? 补充:若服务端实际返回的是 { "A": [...] }(即带外层键的对象),才应使用 first 结构体,并确保JSON tag拼写正确:
type First struct {
A []One `json:"A"`
}
// 然后:var some First; json.Decode(&some)
但根据你给出的原始JSON片段 [ {...} ],无需包装结构体——直用切片最简洁、最安全。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











