
当 go 结构体中某个字段是另一个结构体时,若嵌套字段的值为空(如未初始化或零值),json 序列化后对应字段也会显示为空字符串或默认零值,而非预期内容。根本原因在于结构体实例未被正确赋值,而非标签或类型定义问题。
当 go 结构体中某个字段是另一个结构体时,若嵌套字段的值为空(如未初始化或零值),json 序列化后对应字段也会显示为空字符串或默认零值,而非预期内容。根本原因在于结构体实例未被正确赋值,而非标签或类型定义问题。
在 Go 中,json.Marshal 会严格按结构体字段的实际值进行序列化。以如下定义为例:
type A struct {
Zip string `json:"zip"`
}
type B struct {
Foo string `bson:"foo"`
Bar A `json:"bar"`
}
表面上看,Bar 字段已通过 json:"bar" 显式声明,但若未显式初始化 Bar 的内部字段(如 Zip),其值将保持为 string 类型的零值 "",因此序列化结果为:
{"foo":"some-string-value","bar":{"zip":""}}
✅ 正确做法是:确保嵌套结构体的所有相关字段都被显式赋值。例如:
func main() {
b := B{
Foo: "some-string-value",
Bar: A{Zip: "35000"}, // 关键:显式初始化嵌套结构体 A
}
data, err := json.Marshal(b)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(data))
// 输出:{"foo":"some-string-value","bar":{"zip":"35000"}}
}
⚠️ 注意事项:
- 不可依赖“自动填充”:Go 不会自动为嵌套结构体字段注入默认值或从上下文推导值;
-
零值陷阱:
A{}等价于A{Zip: ""},务必检查是否遗漏字段赋值; -
指针可选优化:若允许嵌套字段为
null或可选,可将Bar A改为Bar *A,此时未赋值时 JSON 中bar为null,且可区分“空值”与“零值”; -
标签一致性:
bson和json标签互不影响,但需确保json标签拼写正确(如json:"bar"而非json:"Bar"),否则字段可能被忽略(首字母小写且无导出标签时)。
总结:嵌套结构体 JSON 序列化失败,99% 的原因是字段未初始化,而非结构体定义或标签错误。调试时优先检查结构体字面量或构造逻辑中是否完整赋值,尤其是深层嵌套层级。











