Flattening marshalled JSON structs with anonymous members in Go

前端 未结 7 1942
感情败类
感情败类 2021-01-02 10:20

Given the following code: (reproduced here at play.golang.org.)

package main

import (
    "encoding/json"
    "fmt"
)

type User struct {         


        
7条回答
  •  礼貌的吻别
    2021-01-02 11:03

    Make use of omitempty tags and a bit of logic so you can use a single type that produces the right output for different cases.

    The trick is knowing when a value is considered empty by the JSON encoder. From the encoding/json documentation:

    The empty values are false, 0, any nil pointer or interface value, and any array, slice, map, or string of length zero.

    Here is your program slightly modified to produce the output you wanted. It omits certain fields when their values are "empty" - specifically, the JSON encoder will omit ints with "0" as value and maps with zero-length.

    package main
    
    import (
        "encoding/json"
        "fmt"
    )
    
    type User struct {
        Id     int               `json:"id"`
        Name   string            `json:"name,omitempty"`
        UserId int               `json:"userId,omitempty"`
        Links  map[string]string `json:"_links,omitempty"`
    }
    
    func Marshal(u *User) ([]byte, error) {
        u.Links = make(map[string]string)
        if u.UserId != 0 {
            u.Links["self"] = fmt.Sprintf("http://user/%d", u.UserId)
        } else if u.Id != 0 {
            u.Links["self"] = fmt.Sprintf("http://session/%d", u.Id)
        }
        return json.MarshalIndent(u, "", "    ")
    }
    
    func main() {
        u := &User{Id: 123, Name: "James Dean"}
        s := &User{Id: 456, UserId: 123}
        json, err := Marshal(u)
        if err != nil {
            panic(err)
        } else {
            fmt.Println(string(json))
        }
        json, err = Marshal(s)
        if err != nil {
            panic(err)
        } else {
            fmt.Println(string(json))
        }
    }
    

    Copy on play.golang.org.

提交回复
热议问题