
本文介绍如何将形如 `[{"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 对象({})。
正确的做法是分两步解析:
- 先将 JSON 解码为 []map[string]string(即字符串映射的切片);
- 再遍历该切片,逐个提取每个子 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("合并后的字典: %+v\n", 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 场景,兼顾简洁性与可扩展性。










