
本文详解如何使用 go 的 `encoding/json` 包安全解析含 `null` 元素的 json 数组,通过自定义结构体与指针接收实现灵活字段提取,并避免因 `null` 导致的解码失败。
Go 语言原生的 json.Unmarshal 对 null 值有明确行为:当目标类型为非指针结构体时,null 会导致解码错误;但若使用*指向结构体的指针切片(`[]Item)**,null会被自动映射为nil`,从而安全跳过——这正是处理混合数据(如部分对象缺失、部分含可选字段)的关键技巧。
以下是一个完整、健壮的解析示例:
package main
import (
"encoding/json"
"fmt"
)
type Item struct {
Id int `json:"id"`
Label string `json:"label,omitempty"`
}
func main() {
data := []byte(`[
{"id": 27},
{"id": 0, "label": "Label 0"},
null,
{"id": 93},
{"id": 85},
{"id": 54},
null,
{"id": 46, "label": "Label 46"}
]`)
var items []*Item
if err := json.Unmarshal(data, &items); err != nil {
fmt.Printf("JSON 解析失败: %v\n", err)
return
}
fmt.Println("解析结果(共", len(items), "项):")
for i, item := range items {
if item == nil {
fmt.Printf("[%d] → nil (原始 JSON 中的 null)\n", i)
} else {
fmt.Printf("[%d] id=%d, label=%q\n", i, item.Id, item.Label)
}
}
}✅ 关键要点说明:
- []*Item 类型允许 null 映射为 nil 指针,避免 panic 或错误中断;
- 字段标签 json:"label,omitempty" 表示该字段在 JSON 中缺失或为空字符串时可忽略,提升兼容性;
- 使用 omitempty 不影响 null 的处理逻辑(null 仍转为 nil,而非空字符串);
- 实际项目中建议对 item != nil 做显式判断,再访问 item.Id 等字段,防止 panic。
⚠️ 注意事项:
- 若误用 []Item(非指针切片),遇到 null 会触发 json: cannot unmarshal null into Go value of type main.Item 错误;
- Label 字段声明为 string 而非 *string 是合理选择:omitempty 已足够应对缺失场景,且语义更清晰(空字符串与缺失可统一按业务逻辑区分);
- 如需保留 null 与空字符串的语义差异,才应将字段定义为 *string。
掌握这一模式后,你可轻松扩展支持更深层嵌套(如 "metadata": {"version": 1, "tags": ["a","b"]}),只需在 Item 中嵌入对应结构体并正确设置 JSON 标签即可。










