json:",omitempty"json:"-"-json:"-,"MarshalJSON() ([]byte, error)UnmarshalJSON(b []byte) error这些都是我们常用的设置技巧。
JSON and struct composition in GoMarshalJSONAlias以下是译文:
encoding/jsonstrcut| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | package main import ( "encoding/json" "os" "time" ) type MyUser struct { ID int64 `json:"id"` Name string `json:"name"` LastSeen time.Time `json:"lastSeen"` } func main() { _ = json.NewEncoder(os.Stdout).Encode( &MyUser{1, "Ken", time.Now()}, ) } | 
序列化的结果:
| 1 | {"id":1,"name":"Ken","lastSeen":"2009-11-10T23:00:00Z"} | 
LastSeenMarshalJSON| 1 2 3 4 5 6 7 8 9 10 11 | func (u *MyUser) MarshalJSON() ([]byte, error) { return json.Marshal(&struct { ID int64 `json:"id"` Name string `json:"name"` LastSeen int64 `json:"lastSeen"` }{ ID: u.ID, Name: u.Name, LastSeen: u.LastSeen.Unix(), }) } | 
这样做当然没有问题,但是如果有很多字段的话就会很麻烦,如果我们能把原始struct嵌入到新的struct中,并让它继承所有不需要改变的字段就太好了:
| 1 2 3 4 5 6 7 8 9 | func (u *MyUser) MarshalJSON() ([]byte, error) { return json.Marshal(&struct { LastSeen int64 `json:"lastSeen"` *MyUser }{ LastSeen: u.LastSeen.Unix(), MyUser: u, }) } | 
MarshalJSON解决办法就是为原始类型起一个别名,别名会有原始struct所有的字段,但是不会继承它的方法:
| 1 2 3 4 5 6 7 8 9 10 | func (u *MyUser) MarshalJSON() ([]byte, error) { type Alias MyUser return json.Marshal(&struct { LastSeen int64 `json:"lastSeen"` *Alias }{ LastSeen: u.LastSeen.Unix(), Alias: (*Alias)(u), }) } | 
UnmarshalJSON| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | func (u *MyUser) UnmarshalJSON(data []byte) error { type Alias MyUser aux := &struct { LastSeen int64 `json:"lastSeen"` *Alias }{ Alias: (*Alias)(u), } if err := json.Unmarshal(data, &aux); err != nil { return err } u.LastSeen = time.Unix(aux.LastSeen, 0) return nil } | 
