
本文详解go语言中解析含嵌套json数组时出现“index out of range”运行时错误的根本原因,指出json格式与go结构体定义不匹配是主因,并提供符合标准的json写法、结构体定义及完整可运行示例。
本文详解go语言中解析含嵌套json数组时出现“index out of range”运行时错误的根本原因,指出json格式与go结构体定义不匹配是主因,并提供符合标准的json写法、结构体定义及完整可运行示例。
在Go中使用encoding/json包解析JSON时,若结构体字段期望接收一个对象数组(如[]ObjectType),则对应的JSON字段必须是一个由JSON对象组成的数组,而非字符串、数字或其他非对象类型。原始代码中错误地将数组元素写作 "name": "foo"(缺少外层花括号),导致该JSON片段语法非法,json.Unmarshal无法正确填充Objects切片——其值保持为nil。对nil切片执行索引操作(如jsontype.Objects[0])必然触发panic: runtime error: index out of range。
✅ 正确的JSON格式必须满足:
- 外层为合法JSON对象(键值对);
- objects字段值为JSON数组;
- 数组中每个元素均为符合ObjectType结构的JSON对象(即用{}包裹的键值对)。
以下是修正后的完整可运行示例:
package main
import (
"fmt"
"encoding/json"
)
type JSONObject struct {
Objects []ObjectType `json:"objects"`
}
type ObjectType struct {
Name string `json:"name"`
}
func main() {
// ✅ 正确:单个JSON对象解析
bytes1 := []byte(`{"name": "foo"}`)
var obj ObjectType
if err := json.Unmarshal(bytes1, &obj); err != nil {
fmt.Printf("Error parsing simple object: %v\n", err)
return
}
fmt.Printf("Simple object name: %s\n", obj.Name) // 输出: foo
// ✅ 正确:含嵌套对象数组的JSON(注意方括号内是 { ... },不是 "...")
bytes2 := []byte(`{"objects": [{"name": "foo"}, {"name": "bar"}]}`)
var jsonObj JSONObject
if err := json.Unmarshal(bytes2, &jsonObj); err != nil {
fmt.Printf("Error parsing array: %v\n", err)
return
}
// 安全访问:检查切片长度再索引
if len(jsonObj.Objects) > 0 {
fmt.Printf("First object name: %s\n", jsonObj.Objects[0].Name) // 输出: foo
}
fmt.Printf("Total objects: %d\n", len(jsonObj.Objects)) // 输出: 2
}
⚠️ 关键注意事项:
- JSON语法严格:["name": "foo"] 是非法JSON;正确写法是[{"name": "foo"}];
- 始终检查Unmarshal返回的error:避免静默失败导致后续逻辑误用未初始化数据;
- 访问切片前务必校验长度:即使JSON合法,空数组也会使len(jsonObj.Objects) == 0,直接索引仍会panic;
- 结构体字段名首字母大写(导出)且标签json:"key"需与JSON键名精确匹配(区分大小写);
- 可考虑使用json.RawMessage或自定义UnmarshalJSON方法处理动态/混合类型场景。
遵循上述规范,即可安全、可靠地解析任意深度嵌套的JSON数组结构。










