Golang 自定义Time类型的JSON字段格式
Go 自身的 time.Time 类型默认解析的日期格式是
RFC3339标准, 也就是2006-01-02T15:04:05Z07:00的格式。
改成自定义类型的思路是:
定义一个内嵌time.Time的结构体,并重写MarshalJSON方法,然后在定义model的时候把time.Time类型替换为我们自己的类型即可。
废话不多说,先上代码片段。
import (
"database/sql/driver"
"fmt"
"time"
)
const TimeFormat = "2006-01-02 15:04:05"
// JSONTime format json time field by myself
type JSONTime struct {
time.Time
}
func (t *JSONTime) UnmarshalJSON(data []byte) (err error) {
if len(data) == 2 {
*t = JSONTime{Time: time.Time{}}
return
}
loc, _ := time.LoadLocation("Asia/Shanghai")
now, err := time.ParseInLocation(`"`+TimeFormat+`"`, string(data), loc)
*t = JSONTime{Time: now}
return
}
// MarshalJSON on JSONTime format Time field with Y-m-d H:i:s
func (t JSONTime) MarshalJSON() ([]byte, error) {
if t.Time.IsZero() {
return []byte("null"), nil
}
formatted := fmt.Sprintf("\"%s\"", t.Format(TimeFormat))
return []byte(formatted), nil
}
// Value insert timestamp into mysql need this function.
func (t JSONTime) Value() (driver.Value, error) {
var zeroTime time.Time
if t.Time.UnixNano() == zeroTime.UnixNano() {
return nil, nil
}
return t.Time, nil
}
// Scan value of time.Time
func (t *JSONTime) Scan(v interface{}) error {
value, ok := v.(time.Time)
if ok {
*t = JSONTime{Time: value}
return nil
}
return fmt.Errorf("can not convert %v to timestamp", v)
}
- 在使用
gorm框架时,用到MarshalJSON/Scan/Value方法。 - 在使用
Gin框架时使用ShouldBindJSON绑定参数会调用UnmarshalJSON,在context.ShouldBindJSON时,会调用field.UnmarshalJSON方法,context.JSON返回 json 时,会调用field.MarshalJSON方法。 - 在使用
go-redis从缓存里取2021-08-26 12:00:00格式的字符串时会调用UnmarshalJSON不需要重新定义 string 类型的字段,解析到缓存数据之后再转成自定义time类型。

977

被折叠的 条评论
为什么被折叠?



