最近開發一個公司項目,發現Go語言結構體Json轉換時,存在時間格式不同問題。在網上找了好久也沒有找到一個很好的方案。即結構體序列化後的格式是`1993-01-01T20:08:23.000000028+08:00`。但爲了兼容公司以往的項目,但願沿用`1993-01-01 20:08:23`這種格式。網上找到了下面的代碼,能夠解決大部分的問題。git
import "time" const ( DateFormat = "2006-01-02" TimeFormat = "2006-01-02 15:04:05" ) type Time time.Time func Now() Time { return Time(time.Now()) } func (t *Time) UnmarshalJSON(data []byte) (err error) { now, err := time.ParseInLocation(`"`+TimeFormat+`"`, string(data), time.Local) *t = Time(now) return } func (t Time) MarshalJSON() ([]byte, error) { b := make([]byte, 0, len(TimeFormat)+2) b = append(b, '"') b = time.Time(t).AppendFormat(b, TimeFormat) b = append(b, '"') return b, nil } func (t Time) String() string { return time.Time(t).Format(TimeFormat) }
可是這樣寫會對原有的struct產生影響,須要將原來的time.Time的變量類型替換成Time。可在使用一些ORM時就不行了,好比Beego的Orm就會報錯了。所以,要在不改變結構體時間類型的狀況下,替換掉原來的時間格式。就只能和上面的代碼同樣,給結構體也實現MarshalJson和UnmarshalJson方法。github
type User struct { Id int `json:"id"` Name string `json:"name"` CreatedAt time.Time `json:"created_at"` } func (u *User) MarshalJSON() ([]byte, error) { type Alias User user := &struct { CreatedAt Time `json:"created_at"` *Alias }{Time(u.CreatedAt), (*Alias)(u)} return json.Marshal(user) } func (u *User) UnmarshalJSON(data []byte) (err error) { type Alias User user := &struct { CreatedAt Time `json:"created_at"` *Alias }{Time(u.CreatedAt), (*Alias)(u)} err = json.Unmarshal(data, user) if err != nil { return err } user.Alias.CreatedAt = time.Time(user.CreatedAt) *u = User(*user.Alias) return nil } func main() { var user *User user = &User{ Id: 4, Name: "Liam", CreatedAt: time.Now(), } bytes, _ := json.Marshal(user) fmt.Printf("%v\n", string(bytes)) data := `{"id":3, "name":"Liam Lian", "created_at":"2017-11-18 19:00:00"}` json.Unmarshal([]byte(data), &user) fmt.Printf("%v\n", user) }
雖然這樣便實現了時間格式的兼容,並且不影響原來的結構體。但若是這樣的結構體比較多的話,就會有不少的這類代碼。因而就要用其餘json包了。如liamylian/jsontimesql
package main import( "fmt" "time" "github.com/liamylian/jsontime" ) var json = jsontime.ConfigWithCustomTimeFormat type User struct { Id int `json:"id"` Name string `json:"name"` CreatedAt time.Time `json:"created_at" time_format:"sql_datetime" time_utc:"false"` } func main() { user := User { Id: 1, Name: "Liam", CreatedAt: time.Now(), } bytes, _ := json.Marshal(user) fmt.Printf("%s", bytes) }