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字段

更多关于Golang中嵌入结构体的JSON序列化异常问题探讨的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


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}
}
回到顶部