
go语言中,嵌入结构体序列化为json时返回空对象{},根本原因是字段未导出(首字母小写),导致encoding/json包无法访问;只需将字段名首字母大写并避免与方法名冲突即可正确序列化。
go语言中,嵌入结构体序列化为json时返回空对象{},根本原因是字段未导出(首字母小写),导致encoding/json包无法访问;只需将字段名首字母大写并避免与方法名冲突即可正确序列化。
在Go中使用json.Marshal()对结构体进行序列化时,只有导出字段(即首字母大写的字段)才会被编码到JSON中。嵌入结构体(embedded struct)也不例外——若其内部字段均为非导出字段(如name string、value int),即使结构体本身被嵌入,json包仍会忽略全部字段,最终输出空JSON对象{}。
以下是一个典型错误示例:
package main
import (
"encoding/json"
"fmt"
)
type Parent struct {
name string // 非导出字段 → 不参与JSON序列化
value int // 非导出字段 → 不参与JSON序列化
}
type Child struct {
Parent // 嵌入Parent
}
func main() {
c := Child{Parent: Parent{name: "Alice", value: 42}}
data, _ := json.Marshal(c)
fmt.Println(string(data)) // 输出:{}
}✅ 正确做法是:将嵌入结构体中的字段改为导出字段(首字母大写),同时注意命名冲突——若结构体还定义了同名方法(如Name()),需重命名字段或方法以避免歧义:
package main
import (
"encoding/json"
"fmt"
)
type Parent struct {
Name string `json:"name"` // 导出字段 + 可选JSON标签
Value int `json:"value"`
}
type Child struct {
Parent // 嵌入后自动获得Name、Value字段
}
func main() {
c := Child{Parent: Parent{Name: "Alice", Value: 42}}
data, err := json.Marshal(c)
if err != nil {
panic(err)
}
fmt.Println(string(data)) // 输出:{"name":"Alice","value":42}
}⚠️ 注意事项:
立即学习“go语言免费学习笔记(深入)”;
- 嵌入结构体的字段可见性独立于嵌入行为:嵌入仅提供组合语法糖,不改变字段导出规则;
- 若需自定义JSON键名,推荐使用json结构体标签(如 `json:"full_name"`);
- 方法(哪怕导出)永远不会被json.Marshal序列化,仅字段参与编码;
- 使用json:",omitempty"可忽略零值字段,提升JSON简洁性。
总结:Go的JSON序列化严格遵循导出规则。要使嵌入结构体正确序列化,请确保所有待导出字段首字母大写,并合理使用结构体标签控制输出格式。这是理解Go组合模型与标准库协同工作的关键实践之一。










