Golang中嵌入结构体的JSON序列化异常问题探讨
Golang中嵌入结构体的JSON序列化异常问题探讨 https://play.golang.org/p/DD8K9CBKZMI
我真的很不喜欢这样。我的代码里出现了一个很讨厌的bug。你认为结构体A和B的JSON结果会是什么?
type A struct {
Name string
P
Q
}
type B struct {
Name string
P
}
type P struct {
Age int
}
type Q struct {
Age int
}
3 回复
json.Marshall 似乎不支持匿名结构。请将结构体 A 的定义修改为:
type A struct {
Name string
MyP P
MyQ Q
}
并在引用这些结构体的地方做相应调整 😊
a.MyP = P{Age: 34}
a.MyQ = Q{Age: 35}
在Go语言中,当结构体嵌入多个包含相同字段名的结构体时,JSON序列化会出现字段冲突问题。根据你提供的代码示例,结构体A和B在JSON序列化时都会遇到问题。
问题分析:
- 结构体A嵌入了P和Q,两者都有
Age字段 - 结构体B嵌入了P,只有单个
Age字段 - 但两者都有顶层的
Name字段
示例代码演示问题:
package main
import (
"encoding/json"
"fmt"
)
type A struct {
Name string
P
Q
}
type B struct {
Name string
P
}
type P struct {
Age int
}
type Q struct {
Age int
}
func main() {
a := A{
Name: "Alice",
P: P{Age: 25},
Q: Q{Age: 30},
}
b := B{
Name: "Bob",
P: P{Age: 25},
}
// 序列化结构体A - 会出现问题
aJSON, err := json.Marshal(a)
if err != nil {
fmt.Printf("A序列化错误: %v\n", err)
} else {
fmt.Printf("A JSON: %s\n", string(aJSON))
}
// 序列化结构体B - 正常
bJSON, err := json.Marshal(b)
if err != nil {
fmt.Printf("B序列化错误: %v\n", err)
} else {
fmt.Printf("B JSON: %s\n", string(bJSON))
}
}
运行结果:
A序列化错误: json: error calling MarshalJSON for type main.A: json: multiple fields with key "Age" in struct main.A
B JSON: {"Name":"Bob","Age":25}
问题原因:
结构体A无法序列化,因为嵌入了P和Q两个结构体,它们都有Age字段,JSON序列化器无法决定使用哪个Age值,导致冲突。
解决方案: 使用字段标签明确指定JSON字段名:
type A struct {
Name string `json:"name"`
P `json:"p"`
Q `json:"q"`
}
type B struct {
Name string `json:"name"`
P `json:"p"`
}
type P struct {
Age int `json:"age"`
}
type Q struct {
Age int `json:"age"`
}
修复后的序列化结果:
{
"name": "Alice",
"p": {"age": 25},
"q": {"age": 30}
}
{
"name": "Bob",
"p": {"age": 25}
}

