
go的json.unmarshal要求结构体字段必须首字母大写(即导出字段),否则无法访问并赋值,即使无报错也会返回零值结构。
在Go语言中,encoding/json 包通过反射机制实现JSON与结构体的双向映射,但反射仅能访问导出(exported)字段——即字段名首字母必须为大写。若字段以小写字母开头(如 status、entryCount),则属于包级私有字段,json.Unmarshal 完全不可见,因此不会进行任何赋值操作,最终结构体保持零值状态(如空字符串、0、false、nil切片等),且不返回错误。
以下是修正后的完整示例代码:
package main
import (
"encoding/json"
"fmt"
)
type Status struct {
NodeID string `json:"node_id"` // 字段名大写 + JSON tag 显式映射
Status string `json:"status"`
}
type Meta struct {
ID string `json:"id"`
From string `json:"from"`
To string `json:"to"`
EntryCount int64 `json:"entryCount"`
Size int64 `json:"size"`
Deprecated bool `json:"deprecated"` // 注意原JSON中是 "deprecated",拼写已修正
}
type MyData struct {
Metadata Meta `json:"metadata"`
Status []Status `json:"status"`
}
func main() {
jsonData := `{
"metadata":{
"id":"2377f625-619b-4e20-90af-9a6cbfb80040",
"from":"2014-12-30T07:23:42.000Z",
"to":"2015-01-14T05:11:51.000Z",
"entryCount":801,
"size":821472,
"deprecated":false
},
"status":[{
"node_id":"de713614-be3d-4c39-a3f8-1154957e46a6",
"status":"PUBLISHED"
}]
}`
var realData MyData
err := json.Unmarshal([]byte(jsonData), &realData)
if err != nil {
fmt.Printf("JSON解析错误: %v\n", err)
return
}
fmt.Printf("解析成功:\n%+v\n", realData)
// 输出示例:
// {Metadata:{ID:"2377f625-619b-4e20-90af-9a6cbfb80040" From:"2014-12-30T07:23:42.000Z" To:"2015-01-14T05:11:51.000Z" EntryCount:801 Size:821472 Deprecated:false} Status:[{NodeID:"de713614-be3d-4c39-a3f8-1154957e46a6" Status:"PUBLISHED"}]}
}✅ 关键要点总结:
- ✅ 所有需参与JSON编解码的结构体字段必须首字母大写(导出);
- ✅ 推荐配合 json:"field_name" 标签,显式指定JSON键名(尤其当Go字段名与JSON key不一致时,如 NodeID ↔ "node_id");
- ✅ 检查拼写一致性:原JSON中为 "deprecated",结构体字段应为 Deprecated(而非 Depricated);
- ✅ json.Unmarshal 返回 nil 错误 ≠ 解析成功,仅表示语法合法;仍需检查字段值是否非零,建议结合单元测试验证;
- ❌ 切勿使用小写字段 + json tag —— tag 无效,字段仍不可见。
遵循导出规则是Go JSON处理的基石,也是避免“静默失败”的第一道防线。
立即学习“go语言免费学习笔记(深入)”;










