https://attilaolah.eu/2014/09/10/json-and-struct-composition-in-go/

Omitting fields

type User struct {
    Email    string `json:"email"`
    Password string `json:"password"`
}

type omit *struct{}

type PublicUser struct {
    *User
    Password omit `json:"password,omitempty"` // Using `bool`, `int` works too
}

json.Marshal(PublicUser{
    User: user,
})
// {
// "email": "[email protected]"
// }
var user PublicUser
json.Unmarshal(`
{
	"email": "[email protected]",
	"password": "123456789"
}`, &v) // password ignored

Adding fields

type PublicUser struct {
    *User
    Token    string `json:"token"`
    Password omit   `json:"password,omitempty"`
}

json.Marshal(PublicUser{
    User:  user,
    Token: token,
})

// {
// "email": "[email protected]",
// "password": "123456789" <- will be omitted
// "token": "a_123" <- will be parsed
// }

Combining structs

type BlogPost struct {
    URL   string `json:"url"`
    Title string `json:"title"`
}

type Analytics struct {
    Visitors  int `json:"visitors"`
    PageViews int `json:"page_views"`
}
var post BlogPost
var analytics Analytics
json.Marshal(struct{
    *BlogPost
    *Analytics
}{post, analytics})

// {
// "url": "a.com",
// "title": "Title"
// "visitors": "12"
// "pageViews": "1000"
// }

json.Unmarshal([]byte(`{
  "url": "[email protected]",
  "title": "Attila's Blog",
  "visitors": 6,
  "page_views": 14
}`), &struct {
  *BlogPost
  *Analytics
}{&post, &analytics})

Renaming fields

type CacheItem struct {
    Key    string `json:"key"`
    MaxAge int    `json:"cacheAge"`
    Value  Value  `json:"cacheValue"`
}

json.Marshal(struct{
    *CacheItem

    // Omit bad keys
    OmitMaxAge omit `json:"cacheAge,omitempty"`
    OmitValue  omit `json:"cacheValue,omitempty"`

    // Add nice keys
    MaxAge int    `json:"max_age"`
    Value  *Value `json:"value"`
}{
    CacheItem: item,

    // Set the int by value:
    MaxAge: item.MaxAge,

    // Set the nested struct by reference, avoid making a copy:
    Value: &item.Value,
})

Going further and dealing with uncertainty in objects

If you only know certain aspects of the struct at compile time, and others depend on the actual JSON object’s values, you can use a package such as https://pkg.go.dev/github.com/go-viper/mapstructure/v2, which allows you to set specific rules and conversions based on contents.