Go 的 encoding/json 包仅能解码导出字段(即首字母大写的字段),小写字母开头的字段会被忽略,导致解码后结构体为空且无错误提示。
go 的 `encoding/json` 包仅能解码导出字段(即首字母大写的字段),小写字母开头的字段会被忽略,导致解码后结构体为空且无错误提示。
在 Go 中,JSON 反序列化依赖于反射机制,而反射只能访问导出(exported)字段——即字段名以大写字母开头的字段。这是 Go 语言的可见性规则决定的:只有导出字段才对外(包括标准库)可见;小写开头的字段属于包内私有,json.Unmarshal 无法读写它们,因此静默跳过,既不填充数据,也不返回错误。
以下是最小复现示例及修正方案:
package main
import (
"encoding/json"
"fmt"
)
func main() {
b := []byte(`{"groups":[{"name":"foo"},{"name":"bar"}]}`)
// ❌ 错误:字段 name 和 groups 均为小写 → 不可导出 → 解码失败
type Group struct{ name string }
var contents struct {
groups []Group
}
err := json.Unmarshal(b, &contents)
fmt.Printf("❌ 错误示例:contents = %+v, err = %v\n", contents, err)
// 输出:contents = {groups:[]}, err = <nil>
// ✅ 正确:字段 Name 和 Groups 首字母大写 → 可导出 → 解码成功
type Group2 struct{ Name string }
var contents2 struct {
Groups []Group2 `json:"groups"` // 可选:显式指定 JSON key 映射
}
err2 := json.Unmarshal(b, &contents2)
fmt.Printf("✅ 正确示例:contents = %+v, err = %v\n", contents2, err2)
// 输出:contents = {Groups:[{Name:foo} {Name:bar}]}, err = <nil>
}? 关键要点:
- 字段必须首字母大写(如 Name, Groups),否则 json 包完全不可见;
- 结构体本身也需导出(若定义为具名类型),但此处使用匿名结构体,只需确保其字段导出即可;
- 推荐配合 json 标签明确映射关系(如 `json:"groups"`),提升可维护性与兼容性;
- 解码失败时 err 为 nil 并不意味着成功——务必检查解码后结构体的实际值,尤其在调试初期。
总结:这不是 json 包的 bug,而是 Go 导出规则与序列化机制协同工作的必然要求。养成“导出字段 + 清晰标签”的习惯,是编写健壮 JSON 处理逻辑的基础。


















