这段主要解释嵌套匿名结构在 marshal or unmarshal 时,field key 的冲突情况。我把 untagged 域 json 化的 key 称为 field key,tagged 域 json 化的 key 称为 tag key。
注意:这里讲的 tagged 域是指设置了 key name 的 tag,没有设置 key name 的 tagged 域在 json 化中使用的还是 filed key。
本段涉及的域处在同一层级,且该层级至少是一层嵌套层。
# 至少是这样的嵌套
type A struct {
Name string
}
type B struct {
Name string
}
type C struct {
Name string
}
type D struct {
A
B
C
}
func TestFeature(t *testing.T) {
d := D{A{"A"}, B{"B"}, C{"C"}}
r, _ := json.Marshal(d)
fmt.Println(string(r))
}
以上 D struct 的 instance 有多个相同名称的域 Name。在对其做 marshal or unmarshal 时应用以下规则:
1、json tagged 的域优先于 untagged 的域考虑。
# 如果 A 的域被 `json:"Name"`,则 B C 里的 Name 域都被忽略。
{"Name":"A"}
2、如果 tagged 域的 tag key 唯一,则被正常 marshal or unmarshal,否则冲突的 tagged 域都被忽略。如果 untagged 域的 field key 唯一,则被正常 marshal or unmarshal,否则冲突的 untagged 域都被忽略。
# 如果 A 和 B 的 Name 域都被 `json:"Name"`,则视为 tag key 冲突,所以两者都被忽略。并且 C 的 Name 域为 untagged,所以 C instance 在这场“Name 域 json 化争夺战”中完全处于下风。最终这场战斗没有人胜出。
# {}
# 如果 A 的 Name 域被 `json:"Nickname"`,则剩下 B C 两个 untagged 域争夺,根据规则,最终没有在 json string 中见到 Name key。
# {"Nickname":"A"}