如何在 Go 中解析含空值的多层级 JSON 数组

11次阅读

如何在 Go 中解析含空值的多层级 JSON 数组

本文介绍如何使用 go 的 `encoding/json` 包安全解析包含 `NULL` 元素和可选字段(如 `label`)的 json 数组,并提取结构化数据。

go 语言原生的 json.Unmarshal 对处理含 null 值和不规则结构的 json 数组非常友好——关键在于正确选择目标类型。你提供的 JSON 是一个顶层 JSON 数组,其元素类型混合:既有对象(如 {“id”: 27}),也有 null,且对象中字段非完全一致(label 是可选的)。直接解码为 []map[String]Interface{} 虽可行,但丧失类型安全与可读性;而使用指针结构体切片([]*Item)是更优雅、健壮的方案。

以下是一个完整、可运行的示例:

package main  import (     "encoding/json"     "fmt" )  type Item struct {     Id    int    `json:"id"`     Label string `json:"label,omitempty"` // 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 解析失败: %vn", 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=%qn", i, item.Id, item.Label)         }     } }

输出效果:

解析结果(共 8 项): [0] → id=27, label="" [1] → id=0, label="Label 0" [2] → nil (原始 JSON 中的 null) [3] → id=93, label="" [4] → id=85, label="" [5] → id=54, label="" [6] → nil (原始 JSON 中的 null) [7] → id=46, label="Label 46"

核心原理说明:

  • 使用 []*Item(结构体指针切片)作为目标类型,json 包会自动将 JSON 数组中的每个对象解码为 *Item,而将 null 解码为 nil 指针,完美保留语义。
  • 字段标签 json:”label,omitempty” 确保 label 缺失时不报错,且默认值为空字符串(string 零值)。
  • 不需要手动判断类型或嵌套循环——Go 的 Unmarshal 已内置对多级、稀疏、含 null 的 JSON 的鲁棒支持。

⚠️ 注意事项:

  • 若需严格区分 “label”: “” 和 “label” 缺失,应将 Label 改为 *string 类型,并配合 omitempty;此时 nil 表示字段不存在,空指针解引用需谨慎。
  • 切勿用 []Item(值类型切片)接收含 null 的数组,否则 null 位置会触发 json: cannot unmarshal null into Go value of type main.Item 错误。
  • 生产环境中建议始终检查 err 并做日志/错误处理,而非仅打印后 return。

掌握这种基于结构体 + 指针切片 + 标签控制的模式,即可高效、安全地解析绝大多数现实场景中的“多层级”或“不规则” JSON 数据。

text=ZqhQzanResources