首页 >后端开发 >Golang >如何在 Go 中惯用地嵌入带有自定义 `MarshalJSON()` 的结构?

如何在 Go 中惯用地嵌入带有自定义 `MarshalJSON()` 的结构?

Patricia Arquette
Patricia Arquette原创
2024-12-06 13:18:11284浏览

How to Idiomatically Embed a Struct with a Custom `MarshalJSON()` in Go?

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

当嵌入结构定义自定义 MarshalJSON() 方法时,就会出现挑战,导致意外的 JSON 序列化行为当试图编组包含struct.

背景

考虑以下结构定义:

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

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

按预期编组 Employee 结构很简单:

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),
    })
}

现在,编组 Employee 会生成带有 name 字段的输出转换为大写但缺少 jobRole 字段:

{"name":"BOB"}

惯用语解决方案

为了维持所需的序列化行为,请避免在嵌入结构 (Person) 上定义 MarshalJSON() 方法。相反,创建一个封装自定义编组逻辑的单独类型并嵌入该类型:

type Name string

func (n Name) MarshalJSON() ([]byte, error) {
    return json.Marshal(struct{
        Name string `json:"name"`
    }{
        Name: strings.ToUpper(string(n)),
    })
}

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

此方法将编组自定义隔离为专用类型,防止在其他地方嵌入 Person 结构时出现意外的副作用。

示例:https://play.golang.org/p/u96T4C6PaY

以上是如何在 Go 中惯用地嵌入带有自定义 `MarshalJSON()` 的结构?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn