为了账号安全,请及时绑定邮箱和手机立即绑定

编组类型时如何将方法结果嵌入到 JSON 输出中?

编组类型时如何将方法结果嵌入到 JSON 输出中?

Go
缥缈止盈 2021-10-04 18:16:05
我正在寻找一种干净的方法来将方法的返回值嵌入到类型/值的 JSON 编组中。如果我不需要编写自定义 JSON marshaller,那就太好了。例如,如果用户类型具有FirstName与LastName字段和FullName()方法,我怎样才能容易地嵌入一个full_name字段到JSON输出? type User struct {     FirstName string `json:"first_name"`     LastName  string `json:"last_name"` } func (u User) FullName() string {     return fmt.Sprintf("%s %s", u.FirstName, u.LastName) }预期的 JSON: {     "first_name": "John",     "last_name":  "Smith",     "full_name":  "John Smith" }
查看完整描述

3 回答

?
智慧大石

TA贡献1946条经验 获得超3个赞

如果不提供一些编组器,这将无法轻松处理。我知道您不想MarshalJSON手动编写并完成所有操作,但是您可以尝试在自定义编组器中扩展您的结构,而不是依赖默认编组器。概念证明:


type User struct {

    FirstName string `json:"first_name"`

    LastName  string `json:"last_name"`

}


func (u *User) FullName() string {

    return fmt.Sprintf("%s %s", u.FirstName, u.LastName)

}


func (u User) MarshalJSON() ([]byte, error) {

    type rawUser User // raw struct, without methods (and marshaller)       

    // Marshal rawUser with an extension

    return json.Marshal(struct {

        rawUser

        FullName string `json:"full_name"`

    }{rawUser(u), u.FullName()})

}


您需要强制User转换rawUser为删除所有方法 - 否则您将无限循环MarshalJSON. 此外,我选择MarshalJSON对副本而不是指针进行操作,以确保json.Marshal(user)产生与json.Marshal(&user).


这不是单行代码,而是隐藏了标准接口背后的复杂性,因此您无需记住有一种特殊的非标准方式将您的结构转换为 JSON。


查看完整回答
反对 回复 2021-10-04
?
陪伴而非守候

TA贡献1757条经验 获得超8个赞

您可以创建一个新类型并将其编码为 JSON。如果包含 type 的匿名字段*User,则两者合并:


type UserForJSON struct {

    *User

    FullName string `json:"full_name"`

}


func NewUserForJSON(u *User) *UserForJSON {

    return &UserForJSON{u, u.FullName()}

}


func main() {

    u := &User{"John", "Smith"}

    j, _ := json.Marshal(NewUserForJSON(u))

    fmt.Print(string(j))


}


如果我们可以让 User 实现json.Marshaller,并在幕后User.MarshalJSON()创建一个UserForJSON对象,那就太好了,但这会导致无限递归。


查看完整回答
反对 回复 2021-10-04
?
UYOU

TA贡献1878条经验 获得超4个赞

我不确定它是否是“最好”的方法,但它非常简单。


func (u User) FullNameMarshal() []byte {

    u.FullName = u.FirstName + " " + u.LastName

    uj, err := json.Marshal(&u)

    if err != nil {

        fmt.Println(err)

    }

    return uj

}


查看完整回答
反对 回复 2021-10-04
  • 3 回答
  • 0 关注
  • 163 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信