如何在 Go 中解析包含多个键值对对象的 JSON 数组并合并为单一 map

8次阅读

如何在 Go 中解析包含多个键值对对象的 JSON 数组并合并为单一 map

本文介绍如何将形如 `[{“key1″:”val1”},{“key2″:”val2”}]` 的 json 数组解析为一个统一的 `map[String]string`,涵盖解码流程、类型选择、遍历合并技巧及常见注意事项。

go 中处理 jsON 数据时,若原始数据是以多个独立对象组成的数组形式存在(例如 [{“Cat”:”small animal”},{“Cow”:”Big animal”}]),而非单个扁平对象(如 {“Cat”:”small animal”,”Cow”:”Big animal”}),则不能直接 json.Unmarshal 到 map[string]string——因为 json 格式不匹配:前者是 JSON 数组([]),后者是 JSON 对象({})。

正确的做法是分两步解析

  1. 先将 JSON 解码为 []map[string]string(即字符串映射的切片);
  2. 再遍历该切片,逐个提取每个子 map 的键值对,并合并到一个新的 map[string]string 中。

以下是完整可运行示例:

package main  import (     "encoding/json"     "fmt"     "log" )  func main() {     // 原始 JSON 必须是数组格式:用方括号 [] 包裹多个对象     jsonText := []byte(`[         {"Cat": "small animal"},         {"Cow": "Big animal"},         {"Dog": "loyal pet"}     ]`)      var rawList []map[string]string     if err := json.Unmarshal(jsonText, &rawList); err != nil {         log.Fatal("JSON 解析失败:", err)     }      // 合并为单个 map     resultMap := make(map[string]string)     for _, item := range rawList {         for key, value := range item {             resultMap[key] = value // 若存在重复 key,后出现的值会覆盖前者         }     }      fmt.Printf("合并后的字典: %+vn", resultMap)     // 输出: 合并后的字典: map[Cat:small animal Cow:Big animal Dog:loyal pet] }

关键说明

  • 输入 JSON 必须是合法数组(以 [ 开头、] 结尾),否则 json.Unmarshal 会报错 invalid character … expecting [。
  • 使用 []map[string]string 是最直观且安全的中间类型——它明确表达了“多个无序键值对对象的集合”。
  • 若原始数据实际是 {…} 包裹(即顶层为对象而非数组),需先确认其结构是否为「带字段名的包装对象」(如 {“data”: […]}),此时应定义结构体解析,而非强行转为 []map。
  • 合并逻辑中未做 key 冲突校验;如业务要求检测重复键,可在内层循环添加 if _, exists := resultMap[key]; exists { /* 处理冲突 */ }。

? 进阶建议

  • 对于大规模数据,可考虑使用 json.Decoder 流式解析避免内存峰值;
  • 若键类型不固定(如含数字或空格),建议统一用 map[string]Interface{} + 类型断言,再转换为目标类型;
  • 生产环境推荐配合 json.RawMessage 或自定义 UnmarshalJSON 方法提升健壮性与可维护性。

通过该模式,你可灵活应对各类“分散式键值对集合”的 JSON 场景,兼顾简洁性与可扩展性。

text=ZqhQzanResources