Go语言内置的 json 包使用RFC3339
标准中定义的时间格式,对我们序列化时间字段的时候有很多限制:
package main
import (
"encoding/json"
"fmt"
"time"
)
type Post struct {
CreateTime time.Time `json:"create_time"`
}
func timeFieldDemo() {
p1 := Post{CreateTime: time.Now()}
b, err := json.Marshal(p1)
if err != nil {
fmt.Printf("json.Marshal p1 failed, err:%vn", err)
return
}
fmt.Printf("str:%sn", b)
// str:{"create_time":"2020-12-06T12:22:48.9799258+08:00"}
jsonStr := `{"create_time":"2020-12-06 12:22:10"}`
var p2 Post
if err := json.Unmarshal([]byte(jsonStr), &p2); err != nil {
fmt.Printf("json.Unmarshal failed, err:%vn", err)
// json.Unmarshal failed, err:parsing time ""2020-12-06 12:22:10"" as ""2006-01-02T15:04:05Z07:00"": cannot parse " 12:22:10"" as "T"
return
}
fmt.Printf("p2:%#vn", p2)
}
func main() {
timeFieldDemo()
}
也就是内置的json包不识别我们常用的字符串时间格式,如2020-12-06 12:22:10,不过可以通过实现json.Marshaler
/json.Unmarshaler
接口实现自定义的事件格式解析
首先你需要知道的是,如果你能够为某个类型实现了MarshalJSON()([]byte, error)
和UnmarshalJSON(b []byte) error
方法,那么这个类型在序列化(MarshalJSON)/反序列化(UnmarshalJSON)时就会使用你定制的相应方法
package main
import (
"encoding/json"
"fmt"
"time"
)
const timeLayout = "2006-01-02 15:04:05"
type PostDemo struct {
Title string `json:"title"`
CreatedTime time.Time `json:"created_time"`
}
func (t *PostDemo) MarshalJSON() ([]byte, error) {
type TempPostDemo PostDemo // 定义与PostDemo字段一致的新类型
return json.Marshal(struct {
CreatedTime string `json:"created_time"`
*TempPostDemo // // 避免直接嵌套PostDemo进入死循环
}{
CreatedTime: t.CreatedTime.Format(timeLayout),
TempPostDemo: (*TempPostDemo)(t),
})
}
func (t *PostDemo) UnmarshalJSON(bytes []byte) error {
type TempPostDemo PostDemo
ot := struct {
CreatedTime string `json:"created_time"`
*TempPostDemo
}{
TempPostDemo: (*TempPostDemo)(t),
}
if err := json.Unmarshal(bytes, &ot); err != nil {
return err
}
var err error
t.CreatedTime, err = time.Parse(timeLayout, ot.CreatedTime)
if err != nil {
return err
}
return nil
}
func main() {
t1 := PostDemo{
Title: "编程时光",
CreatedTime: time.Now(),
}
// 通过自定义的MarshalJSON方法实现struct -> json string
b, err := json.Marshal(&t1) // 此处传入指针类型
if err != nil {
fmt.Printf("json.Marshal failed, err:%vn", err)
}
fmt.Printf("str:%sn", b)
// 通过自定义的UnmarshalJSON方法实现json string -> struct
jsonStr := `{"created_time":"2020-12-06 12:28:45","title":"编程时光"}`
var t2 PostDemo
if err := json.Unmarshal([]byte(jsonStr), &t2); err != nil {
fmt.Printf("json.Unmarshal failed, err:%vn", err)
return
}
fmt.Printf("t2:%#vn", t2)
}
// str:{"created_time":"2020-12-06 22:10:44","title":"编程时光"}
// t2:main.PostDemo{Title:"编程时光", CreatedTime:time.Time{wall:0x0, ext:63742854525, loc:(*time.Location)(nil)}}