发布于2026-07-10 阅读(0)
扫一扫,手机访问
go 的 json 包只能序列化导出(首字母大写)的结构体字段;若 calendarday 中的字段为小写(如 day、weekday),则会被忽略,导致 json 输出为空对象 {}。
在 Go 日常开发中,JSON 序列化是个高频操作,但很多人初学时都会踩到一个坑:明明结构体切片里有数据,序列化出来却只有一对空大括号 —— {}。这种问题其实很典型,根源就在于 Go 的 JSON 序列化机制有一个硬性规则。
Go 标准库的 encoding/json 包在序列化时,依赖的是反射机制。而这个机制的限制非常直接:反射只能访问导出的字段。所谓导出字段,就是那些以大写字母开头的字段名。换句话说,如果你结构体里写的是 day 和 weekday,它们都是小写首字母,属于未导出字段。那么不管是 json.Marshal 还是 json.NewEncoder.Encode,都会直接跳过它们。即使你的切片非空,最终输出的也只能是一个空对象。
所以,正确的做法其实很简单:把字段名改为大写开头,同时通过 JSON 标签(tag)控制序列化后的键名。就像下面这样:
type CalendarDay struct {
Day int `json:"day"` // 导出字段:Day → 对应 JSON key "day"
Weekday string `json:"weekday"` // 导出字段:Weekday → 对应 JSON key "weekday"
}
另外,别忘了确认外层结构体 CalendarYear 中的字段也是导出的。从你给出的定义来看,January、February 等字段名都是大写开头,这部分本身是正确的。
这里有几个值得注意的细节:
json:"day")只控制序列化后的键名,并不会改变字段的可见性。很多新手会误以为加了标签就能解决,其实不然。,omitempty。比如 json:"day,omitempty",这样当 Day 为 0 时,该字段会被忽略。json.MarshalIndent 来获得格式化的输出,一眼就能看清数据结构:data, _ := json.MarshalIndent(year, "", " ") fmt.Println(string(data))
完整修复之后,调用 getYear(2015) 再编码,你就能得到想要的 JSON 结构了:
{
"january": [
{"day": 1, "weekday": "Thursday"},
{"day": 2, "weekday": "Friday"},
...
],
"february": [...],
...
}
说到底,Go 的序列化安全模型并不是在为难你。它强制要求显式导出字段,本质上是一种封装性与 API 明确性的设计选择。遇到 JSON 输出空对象的问题时,第一反应就去检查结构体字段是否首字母大写——这条经验,能解决 90% 的相似问题。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8