How to not marshal an empty struct into JSON with Go?

前端 未结 4 2103
一个人的身影
一个人的身影 2020-12-04 15:22

I have a struct like this:

type Result struct {
    Data       MyStruct  `json:\"data,omitempty\"`
    Status     string    `json:\"status,omitempty\"`
    R         


        
4条回答
  •  -上瘾入骨i
    2020-12-04 15:29

    As @chakrit mentioned in a comment, you can't get this to work by implementing json.Marshaler on MyStruct, and implementing a custom JSON marshalling function on every struct that uses it can be a lot more work. It really depends on your use case as to whether it's worth the extra work or whether you're prepared to live with empty structs in your JSON, but here's the pattern I use applied to Result:

    type Result struct {
        Data       MyStruct
        Status     string   
        Reason     string    
    }
    
    func (r Result) MarshalJSON() ([]byte, error) {
        return json.Marshal(struct {
            Data     *MyStruct   `json:"data,omitempty"`
            Status   string      `json:"status,omitempty"`
            Reason   string      `json:"reason,omitempty"`
        }{
            Data:   &r.Data,
            Status: r.Status,
            Reason: r.Reason,
        })        
    }
    
    func (r *Result) UnmarshalJSON(b []byte) error {
        decoded := new(struct {
            Data     *MyStruct   `json:"data,omitempty"`
            Status   string      `json:"status,omitempty"`
            Reason   string      `json:"reason,omitempty"`
        })
        err := json.Unmarshal(b, decoded)
        if err == nil {
            r.Data = decoded.Data
            r.Status = decoded.Status
            r.Reason = decoded.Reason
        }
        return err
    }
    

    If you have huge structs with many fields this can become tedious, especially changing a struct's implementation later, but short of rewriting the whole json package to suit your needs (not a good idea), this is pretty much the only way I can think of getting this done while still keeping a non-pointer MyStruct in there.

    Also, you don't have to use inline structs, you can create named ones. I use LiteIDE with code completion though, so I prefer inline to avoid clutter.

提交回复
热议问题