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

我正在寻找一种干净的方法来将方法的返回值嵌入到类型/值的 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"

 }


缥缈止盈
浏览 166回答 3
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。

陪伴而非守候

您可以创建一个新类型并将其编码为 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对象,那就太好了,但这会导致无限递归。

UYOU

我不确定它是否是“最好”的方法,但它非常简单。func (u User) FullNameMarshal() []byte {    u.FullName = u.FirstName + " " + u.LastName    uj, err := json.Marshal(&u)    if err != nil {        fmt.Println(err)    }    return uj}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go