
go 的 json 包只能序列化导出(首字母大写)的结构体字段;若 calendarday 中的字段为小写(如 day、weekday),则会被忽略,导致 json 输出为空对象 {}。
go 的 json 包只能序列化导出(首字母大写)的结构体字段;若 calendarday 中的字段为小写(如 day、weekday),则会被忽略,导致 json 输出为空对象 {}。
在 Go 中,JSON 序列化依赖于反射机制,而该机制仅能访问导出(exported)字段——即字段名必须以大写字母开头。你定义的 CalendarDay 结构体中,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 等均为大写开头):
type CalendarYear struct {
January []CalendarDay `json:"january"`
February []CalendarDay `json:"february"`
// ... 其余月份同理(当前定义已正确)
}? 补充注意事项:
- JSON 标签(如 `json:"day"`)仅控制序列化后的键名,不改变字段的可见性;导出性由字段名首字母决定。
- 若需忽略零值字段,可添加 ,omitempty:`json:"day,omitempty"`。
- 可通过 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 包输出空对象问题的第一步。


















