给出以下结构:
type Person {
Name string `json:"name"`
}
type Employee {
Person
JobRole string `json:"jobRole"`
}
我可以按预期轻松地将Employee编码为JSON:
p := Person{"Bob"}
e := Employee{&p, "Sales"}
output, _ := json.Marshal(e)
fmt.Printf("%s\n", string(output))
输出:
但是当嵌入式结构具有自定义
MarshalJSON()
方法时...func (p *Person) MarshalJSON() ([]byte,error) {
return json.Marshal(struct{
Name string `json:"name"`
}{
Name: strings.ToUpper(p.Name),
})
}
它完全破裂:
p := Person{"Bob"}
e := Employee{&p, "Sales"}
output, _ := json.Marshal(e)
fmt.Printf("%s\n", string(output))
现在结果为:
(请注意,缺少
jobRole
字段)这很容易预料...嵌入式
Person
结构实现了MarshalJSON()
函数,该函数被调用。麻烦是,这不是我想要的。我想要的是:
也就是说,通常对
Employee
的字段进行编码,并遵循Person
的MarshalJSON()
方法来编码(marshal)其字段,并交出一些整洁的JSON。现在,我也可以在
MarshalJSON()
中添加Employee
方法,但这要求我知道嵌入式类型也实现MarshalJSON()
,并且(a)复制其逻辑,或者(b)调用Person
的MarshalJSON()
并以某种方式操纵其输出适合我想要的地方。这两种方法似乎都是草率的,并且不是很可靠的证明(如果我某天无法控制的嵌入式类型会添加自定义MarshalJSON()
方法,该怎么办?)这里有没有我没有考虑过的替代方案?
最佳答案
不要将MarshalJSON
放在Person
上,因为它已被提升为外部类型。而是制作一个type Name string
,并让Name
实现MarshalJSON
。然后将Person
更改为
type Person struct {
Name Name `json:"name"`
}
示例:https://play.golang.org/p/u96T4C6PaY
更新
为了更一般地解决这个问题,您将必须在外部类型上实现
MarshalJSON
。内部类型上的方法被提升为外部类型,因此您不会去解决这个问题。您可以让外部类型调用内部类型的MarshalJSON
,然后将其解码为类似于map[string]interface{}
的通用结构,然后添加自己的字段。此示例这样做了,但它具有更改最终输出字段的顺序的副作用https://play.golang.org/p/ut3e21oRdj
关于json - 使用自定义MarshalJSON()方法嵌入结构的惯用方式,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38489776/