json - 使用自定义 MarshalJSON() 方法嵌入结构的惯用方法

标签 json go embedding

给定以下结构:

type Person struct {
    Name string `json:"name"`
}

type Employee struct {
    *Person
    JobRole string `json:"jobRole"`
}

我可以按预期轻松地将 Employee 编码为 JSON:

p := Person{"Bob"}
e := Employee{&p, "Sales"}
output, _ := json.Marshal(e)
fmt.Printf("%s\n", string(output))

输出:

{"name":"Bob","jobRole":"Sales"}

但是当嵌入式结构具有自定义 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))

现在的结果是:

{"name":"BOB"}

(注意明显缺少 jobRole 字段)

这很容易预料到...嵌入的 Person 结构实现了正在调用的 MarshalJSON() 函数。

问题是,这不是我想要的。我想要的是:

{"name":"BOB","jobRole":"Sales"}

也就是说,正常编码 Employee 的字段,并遵循 PersonMarshalJSON() 方法来编码其字段,并且返回一些整洁的 JSON。

现在我也可以向 Employee 添加一个 MarshalJSON() 方法,但这需要我知道嵌入类型实现了 MarshalJSON() 以及 (a) 复制其逻辑,或 (b) 调用 PersonMarshalJSON() 并以某种方式操纵其输出以适合我想要的位置.这两种方法似乎都很草率,而且不是很适合 future (如果某天我无法控制的嵌入式类型添加自定义 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/

相关文章:

json - 如何迭代 JSON 数组以在 jasperreports 中创建重复报告

go - 在 go 函数声明中的参数旁边时, "..."是什么意思?

go - 在Go中执行模板后,是否可以使用新网址重定向页面?

mysql - 将 Sql 结果集存储在嵌套结构中,如果为空则省略

tensorflow - TensorFlow中的feature_column.embedding_column和keras.layers.Embedding之间的区别

rest - 在 RESTful API 中包含/嵌入与链接

java - GSON 解析 - 不同类型的相同 key

javascript - 无法使用 Ajax 检索 JSON

c# - JSON 数字根到通用名称

c++ - 在 C++ 中嵌入 Lua