鉴于以下结构:
type Person {
Name string `json:"name"`
}
type Employee {
Person
JobRole string `json:"jobRole"`
}
Run Code Online (Sandbox Code Playgroud)
我可以按照预期轻松地将Employee编组为JSON:
p := Person{"Bob"}
e := Employee{&p, "Sales"}
output, _ := json.Marshal(e)
fmt.Printf("%s\n", string(output))
Run Code Online (Sandbox Code Playgroud)
输出:
{ "名": "鲍勃", "jobRole": "销售"}
但是当嵌入式结构有一个自定义MarshalJSON()方法时......
func (p *Person) MarshalJSON() ([]byte,error) {
return json.Marshal(struct{
Name string `json:"name"`
}{
Name: strings.ToUpper(p.Name),
})
}
Run Code Online (Sandbox Code Playgroud)
它彻底打破了:
p := Person{"Bob"}
e := Employee{&p, "Sales"}
output, _ := json.Marshal(e)
fmt.Printf("%s\n", string(output))
Run Code Online (Sandbox Code Playgroud)
现在结果是:
{ "名": "BOB"}
(注意显着缺乏jobRole领域)
这很容易预料......嵌入式Person结构实现了MarshalJSON()被调用的函数.
麻烦的是,这不是我想要的.我想要的是:
{ "名": "BOB", "jobRole": "销售"}
也就是说,Employee正常编码的字段,并推迟编组其字段Person的MarshalJSON()方法,并交回一些整洁的JSON.
现在,我可以一个添加MarshalJSON()方法Employee为好,但这个要求,我知道,嵌入式类型实现MarshalJSON(),以及,或者(a)复制它的逻辑,或(b)调用Person的MarshalJSON()并以某种方式操纵它的输出,以适应,我想它.这两种方法看起来都很邋and,而且不是很有前途的证明(如果某天我不控制的嵌入式类型会增加一个自定义MarshalJSON()方法怎么办?)
这里有没有我没有考虑的替代方案?
不要穿MarshalJSON,Person因为它被提升为外部类型.而是制定type Name string并Name实施MarshalJSON.然后Person改为
type Person struct {
Name Name `json:"name"`
}
Run Code Online (Sandbox Code Playgroud)
示例:https://play.golang.org/p/u96T4C6PaY
更新
为了更普遍地解决这个问题,你将不得不MarshalJSON在外部类型上实现.内部类型的方法被提升为外部类型,所以你不会绕过它.你可以让外部类型调用内部类型,MarshalJSON然后将其解组为通用结构,map[string]interface{}并添加自己的字段.此示例执行此操作但它具有更改最终输出字段的顺序的副作用
https://play.golang.org/p/ut3e21oRdj
| 归档时间: |
|
| 查看次数: |
1239 次 |
| 最近记录: |