
本文介绍如何使用 go 语言解析含两级动态分组的 json 文件——第一级为未知数量的配置组,每组内固定包含 rules 和 configs 两个子对象,其键值对数量和名称均不固定。
本文介绍如何使用 go 语言解析含两级动态分组的 json 文件——第一级为未知数量的配置组,每组内固定包含 rules 和 configs 两个子对象,其键值对数量和名称均不固定。
在 Go 中处理结构不完全固定的 JSON 数据时,核心思路是:对已知层级关系建模,对动态字段使用 map[string]string(或更通用的 map[string]any),并结合切片([]T)容纳未知数量的同级对象。
根据问题描述,JSON 实际结构应为一个数组,其中每个元素代表一个一级分组;每个一级分组是一个对象,内含两个固定字段 "rules" 和 "configs",二者均为键值对集合(即 JSON 对象)。注意:原始问题中给出的 JSON 片段语法不合法(缺少字段名、括号嵌套错误),正确格式示例如下:
[
{
"rules": {
"rule1": "doA",
"rule2": "doB"
},
"configs": {
"config1": "goA",
"configX": "goB"
}
},
{
"rules": {
"rule100": "doAAA",
"rule200": "doBBB"
},
"configs": {
"config100": "goAAA",
"configX00": "goBBB"
}
}
]对应 Go 结构体定义如下:
type ConfigGroup struct {
Rules map[string]string `json:"rules"`
Configs map[string]string `json:"configs"`
}
// 整个 JSON 文件解析为 []ConfigGroup
var groups []ConfigGroup
data, err := os.ReadFile("config.json")
if err != nil {
log.Fatal("读取文件失败:", err)
}
if err := json.Unmarshal(data, &groups); err != nil {
log.Fatal("JSON 解析失败:", err)
}
// 遍历并访问各字段
for i, g := range groups {
fmt.Printf("第 %d 组规则:\n", i+1)
for k, v := range g.Rules {
fmt.Printf(" rule %q → %q\n", k, v)
}
fmt.Printf("第 %d 组配置:\n", i+1)
for k, v := range g.Configs {
fmt.Printf(" config %q → %q\n", k, v)
}
}✅ 关键要点说明:
- 使用
map[string]string精准匹配“未知键名 + 字符串值”的语义,比map[string]any更安全、无需类型断言; - 若 value 可能为多种类型(如 bool、number),则改用
map[string]any并配合类型断言或json.RawMessage延迟解析; -
json.Unmarshal要求目标变量地址(&groups),切片需预先声明(非 nil); - 实际项目中建议添加字段存在性检查(如
if g.Rules == nil)避免 panic; - 可进一步封装为方法(如
g.Rules.Get("rule1"))提升可读性与容错能力。
通过该模式,你既能保持代码类型安全,又能灵活应对 JSON 中动态增减的键值对,适用于配置中心、规则引擎等典型场景。


















