Golang 自定义Time类型的JSON字段格式

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)
}

  1. 在使用 gorm 框架时,用到 MarshalJSON / Scan / Value 方法。
  2. 在使用 Gin 框架时使用 ShouldBindJSON 绑定参数会调用 UnmarshalJSON,在 context.ShouldBindJSON 时,会调用 field.UnmarshalJSON方法, context.JSON 返回 json 时,会调用 field.MarshalJSON 方法。
  3. 在使用 go-redis 从缓存里取 2021-08-26 12:00:00 格式的字符串时会调用 UnmarshalJSON 不需要重新定义 string 类型的字段,解析到缓存数据之后再转成自定义time类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值