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.
// /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=±nnn.
if t.wall&hasMonotonic != 0 {
m2 := )
sign := byte('+')
< 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)
error parse new}
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}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论