douxuanpa8298 2018-06-13 07:59
浏览 315
已采纳

都实现MarshalJSON()的复合结构的JSON封送处理

I faced recently the following problem and have not found any solution. I have two struct types in Go, let us call them Parent and Child. Child has an anonymous field of the type *Parent. However, Parent has a field called "ID" which has the type of a third struct which type we will call "IDType" (in my real problem this is a dialect/sql.NullInt64). IDType has an int field and a bool field.

The problem is the following: Both, Parent and Child, implement MarshalJSON() because for Parent I only want the int field inside the JSON and for Child the same. However, it seems that both MarshalJSONs infer with the result that only the values of Parent are encoded in the final JSON.

Maybe a minimal example makes it easier to understand:

package main

import (
    "encoding/json"
    "fmt"
    "os"
)

type IDType struct {
    Value int
    Valid bool
}

type Parent struct {
    ID         IDType `json:"id"`
    SomeString string `json:"some_string"`
}

type Child struct {
    *Parent
    Status int `json:"status"`
}

func (parent *Parent) MarshalJSON() ([]byte, error) {
    type Alias Parent
    fmt.Println("Parent")
    return json.Marshal(struct {
        *Alias
        ID int `json:"id"`
    }{
        Alias: (*Alias)(parent),
        ID:    parent.ID.Value,
    })
}

func (child *Child) MarshalJSON() ([]byte, error) {
    type Alias Child
    fmt.Println("Child")
    return json.Marshal(struct {
        *Alias
        Status int `json:"status"`
    }{
        Alias:  (*Alias)(child),
        Status: child.Status,
    })
}

func main() {
    ID := IDType{Value: 1, Valid: true}
    parent := Parent{ID: ID, SomeString: "Hello"}
    child := Child{Parent: &Parent{ID: ID, SomeString: "Hello"}, Status: 1}
    json.NewEncoder(os.Stdout).Encode(&parent)
    json.NewEncoder(os.Stdout).Encode(&child)
}

The output is:

Parent
{"some_string":"Hello","id":1}
Child
Parent
{"some_string":"Hello","id":1}

I expect something like:

Parent
{"some_string":"Hello","id":1}
Child
Parent
{"some_string":"Hello","id":1, "status": 1}
  • 写回答

2条回答 默认 最新

  • douyijin7741 2018-06-13 08:47
    关注

    It looks you only define a custom marshaling logic because of the custom ID marshaling. Define your custom marshaling for the IDType type only which is not embedded, so it won't cause any trouble marshaling the other types:

    func (id *IDType) MarshalJSON() ([]byte, error) {
        return json.Marshal(id.Value)
    }
    

    And no other custom marshaling are required. With this, the output will be:

    {"id":1,"some_string":"Hello"}
    {"id":1,"some_string":"Hello","status":1}
    

    Try it on the Go Playground.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器