Go 解决时间序列化
Go时间类型序列化反序列化
系统时间类型
定义结构体
type Person struct {
Birthday time.Time
Name string
}
序列化
func TestMarshal(t *testing.T) {
person := Person{
Birthday: time.Now(),
Name: "leon",
}
data, err := json.Marshal(&person)
if err != nil {
fmt.Println("Marshal Error:",err)
return
}
fmt.Println(string(data))
// {"Birthday":"2021-12-04T19:57:00.291554+08:00","Name":"leon"}
}
- 可以看到序列化后的时间格式是
2021-12-04T19:57:00.291554+08:00这样的
反序列化
func TestUnmarshal(t *testing.T) {
var str = `{"birthday":"2021-12-04T19:57:00.291554+08:00", "name":"leon"}`
var person Person
if err := json.Unmarshal([]byte(str), &person); err != nil{
fmt.Println("Unmarshal Error:",err)
return
}
fmt.Println(person)
// {2021-12-04 19:57:00.291554 +0800 CST leon}
}
-
在定义json字符串时,时间是
2021-12-04T19:57:00.291554+08:00可以正常序列化 -
如果想要 2021-12-04 19:57:00 这种格式的时间,系统库time.Time就无法做到,如果前端传入的参数是这种格式的会出现解析失败的情况,看下列
func TestUnmarshal2(t *testing.T) { var str = `{"birthday":"2021-12-04 19:57:00", "name":"leon"}` var person Person if err := json.Unmarshal([]byte(str), &person); err != nil{ fmt.Println("Unmarshal Error:",err) return } fmt.Println(person) // Unmarshal Error: parsing time "\"2021-12-04 19:57:00\"" as "\"2006-01-02T15:04:05Z07:00\"": cannot parse " 19:57:00\"" as "T" }- 解析失败
-
可以自定义进行时间序列化
自定义时间类型
定义类型
type LocalTime time.Time
-
定义了一种类型
LocalTime其真实类型是time.Time -
如果直接使用
LocalTime类型来定义时间,会出现问题,也是无法进行序列化和反序列化,因为time.Time实现了Unmarshaler和Marshaler接口中的方法,可以正常序列化操作。 -
所以我们自定义的
LocalTime类型 也要实现Unmarshaler和Marshaler接口中的方法 -
可以先观察一下 time.Time 是如何实现的
func (t Time) MarshalJSON() ([]byte, error) { if y := t.Year(); y < 0 || y >= 10000 { // RFC 3339 is clear that years are 4 digits exactly. // See golang.org/issue/4556#c15 for more discussion. return nil, errors.New("Time.MarshalJSON: year outside of range [0,9999]") } b := make([]byte, 0, len(RFC3339Nano)+2) b = append(b, '"') b = t.AppendFormat(b, RFC3339Nano) b = append(b, '"') return b, nil }func (t *Time) UnmarshalJSON(data []byte) error { // Ignore null, like in the main JSON package. if string(data) == "null" { return nil } // Fractional seconds are handled implicitly by Parse. var err error *t, err = Parse(`"`+RFC3339+`"`, string(data)) return err } -
另外需要重点注意,也需要实现系统的
String() string否则反序列化读取数据是,解析出来的数据是二进制数据,不是正确的类型,可以参考一下 time.Time 是如何实现的func (t Time) String() string { s := t.Format("2006-01-02 15:04:05.999999999 -0700 MST") // Format monotonic clock reading as m=±ddd.nnnnnnnnn. if t.wall&hasMonotonic != 0 { m2 := uint64(t.ext) sign := byte('+') if t.ext < 0 { sign = '-' m2 = -m2 } m1, m2 := m2/1e9, m2%1e9 m0, m1 := m1/1e9, m1%1e9 var buf []byte buf = append(buf, " m="...) buf = append(buf, sign) wid := 0 if m0 != 0 { buf = appendInt(buf, int(m0), 0) wid = 9 } buf = appendInt(buf, int(m1), wid) buf = append(buf, '.') buf = appendInt(buf, int(m2), 9) s += string(buf) } return s }- 注意 方法中的
s := t.Format("2006-01-02 15:04:05.999999999 -0700 MST")代码。
- 注意 方法中的
总结
-
自定义需要实现以下的方法
String() string MarshalJSON() ([]byte, error) UnmarshalJSON(data []byte) error
定义结构体
// 定义格式化样式
const (
DefaultTimeFormat = "2006-01-02 15:04:05"
)
type Person struct {
Birthday LocalTime `json:"birthday"`
Name string `json:"name"`
}
序列化
func (t LocalTime) MarshalJSON() ([]byte, error) {
b := make([]byte, 0, len(DefaultTimeFormat)+2)
b = append(b, '"')
b = time.Time(t).AppendFormat(b, DefaultTimeFormat)
b = append(b, '"')
return b, nil
}
反序列化
func (t *LocalTime) UnmarshalJSON(data []byte) (err error) {
now, err := time.ParseInLocation(`"`+DefaultTimeFormat+`"`, string(data), time.Local)
*t = LocalTime(now)
return
}
实现String() string
func (t LocalTime) String() string {
return time.Time(t).Format(DefaultTimeFormat)
}
测试
func TestDate(t *testing.T) {
// 序列化
var p = Person{Name: "leon", Birthday: LocalTime(time.Now())}
data, err := json.Marshal(&p)
if err != nil {
fmt.Println("marshal err", err)
return
}
fmt.Println(string(data))
// 反序列化
src := []byte(`{"birthday":"2020-05-26 20:20:44","name":"leon"}`)
var pp Person
json.Unmarshal(src,&pp)
fmt.Println(pp)
}
{"birthday":"2021-12-04 20:32:26","name":"leon"}
{2020-05-26 20:20:44 leon}
浙公网安备 33010602011771号