
Go 中解析含嵌套数组的 JSON 时,若 JSON 数组元素格式与 Go 结构体字段类型不匹配(如将字符串误作对象),会导致结构体切片字段为 nil,进而触发 index out of range panic。
go 中解析含嵌套数组的 json 时,若 json 数组元素格式与 go 结构体字段类型不匹配(如将字符串误作对象),会导致结构体切片字段为 nil,进而触发 `index out of range` panic。
在 Go 的 encoding/json 包中,JSON 到 Go 结构体的反序列化严格依赖类型一致性。问题代码中,jsonobject.Objects 字段被定义为 []ObjectType 类型,意味着 JSON 中对应的 "objects" 字段必须是一个由 ObjectType 对应的 JSON 对象组成的数组——即每个数组元素都应是形如 {"name": "..."} 的完整对象。
然而,原始代码中传入的错误 JSON 是:
{ "objects": [ "name": "foo" ] }该写法根本不是合法 JSON:方括号内 "name": "foo" 缺少外层花括号,语法非法(JSON 数组元素不能是键值对裸写)。即使忽略语法错误,其意图也混淆了「字符串字面量」与「对象字面量」——Go 的 []ObjectType 无法从字符串数组(如 ["foo"])或非法片段中解包出结构体字段。
✅ 正确的 JSON 必须为:
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
{ "objects": [ {"name": "foo"} ] }此时,json.Unmarshal 才能将数组中的每个 {...} 映射为一个 ObjectType 实例,并正确初始化 jsontype.Objects 切片(长度为 1,非 nil)。
以下是修复后的完整可运行示例:
package main
import (
"fmt"
"encoding/json"
)
type JSONObject struct {
Objects []ObjectType `json:"objects"`
}
type ObjectType struct {
Name string `json:"name"`
}
func main() {
// ✅ 正确:单个对象解析
bytes := []byte(`{"name": "foo"}`)
var obj ObjectType
if err := json.Unmarshal(bytes, &obj); err != nil {
panic(err)
}
fmt.Printf("Single object: %s\n", obj.Name) // 输出: foo
// ✅ 正确:含合法对象数组的 JSON
bytes = []byte(`{"objects": [{"name": "foo"}, {"name": "bar"}]}`)
var jsonObj JSONObject
if err := json.Unmarshal(bytes, &jsonObj); err != nil {
panic(err)
}
// 安全访问:检查切片长度再索引
if len(jsonObj.Objects) > 0 {
fmt.Printf("First object name: %s\n", jsonObj.Objects[0].Name) // 输出: foo
} else {
fmt.Println("No objects found")
}
}? 关键注意事项:
- 永远验证 json.Unmarshal 返回的 error:非法 JSON 会返回非 nil 错误,而非静默失败;
- 访问切片前务必检查长度:即使 JSON 合法,空数组也会使 Objects 为 []ObjectType{}(长度 0),直接索引 [0] 仍 panic;
- 使用 json.Valid() 预检 JSON 格式(可选):避免因无效 JSON 导致不可预期行为;
- 结构体字段名首字母大写:确保可导出(如将 jsonobject 改为 JSONObject),符合 Go 惯例并避免序列化失败。
遵循类型严格对应与防御性编程原则,即可彻底规避此类 runtime error。

















