问题描述:

gorm中使用下面的CreatedAt 和UpdateAt,可以实现在记录创建和更新时自动更新下面两个字段。虽然使用默认的json解析,从json中到golang中,从golang中写入到数据库(mysql)都是标准的格式“2006-01-02 15:04:05”,但是从golang中解析到json中时是“RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"”。

原因:

time.Time的反序列化使用的是RFC3339Nano,不是希望的标准时间,返回到前台,前台表示拒绝……。只能后台改一下了。

<pre><code>type User struct { Id int64 `json:"id"` CreatedAt time.Time `json:"created_at" ` UpdatedAt time.Time `json:"updated_at" ` }</code></pre> <pre><code> const ( ANSIC = "Mon Jan _2 15:04:05 2006" UnixDate = "Mon Jan _2 15:04:05 MST 2006" RubyDate = "Mon Jan 02 15:04:05 -0700 2006" RFC822 = "02 Jan 06 15:04 MST" RFC822Z = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone RFC850 = "Monday, 02-Jan-06 15:04:05 MST" RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST" RFC1123Z = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone RFC3339 = "2006-01-02T15:04:05Z07:00" RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00" Kitchen = "3:04PM" // Handy time stamps. Stamp = "Jan _2 15:04:05" StampMilli = "Jan _2 15:04:05.000" StampMicro = "Jan _2 15:04:05.000000" StampNano = "Jan _2 15:04:05.000000000" ) // MarshalJSON implements the json.Marshaler interface. // The time is a quoted string in RFC 3339 format, with sub-second precision added if present. 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 }</code></pre>

解决方法:

1.自定义解析方式。在从golang中解析到json时自定义方法重载原生time的解析方法。

详细见下文。

2.使用string作为时间的接收类型。

使用string,不过需要把数据库里的字段类型也改,不然返回还是“2006-01-02T15:04:05.999999999Z07:00”。

3.使用时间戳,只发送给前端时间戳。

使用时间戳,只保存时间戳,返回给前端时间戳,让前端自己格式化。

 

第一种方法代码:

定义自己的时间类型(建议放在utils通用函数包里):

<pre><code>//完整方法 type ProgramModel struct { BaseModel Name string `json:"name" gorm:"column:name"` StartTime BaseModel `json:"start_time" gorm:"column:start_time"` EndTime BaseModel `json:"end_time" gorm:"column:end_time"` } type BaseModel struct { gorm.Model Id uint64 `gorm:"primary_key;AUTO_INCREMENT;column:id" json:"id"` CreatedAt MyTime `gorm:"column:created_at" json:"created_at"` UpdatedAt MyTime `gorm:"column:updated_at" json:"updated_at"` } type MyTime struct { time.Time } //重写 MarshaJSON 方法,在此方法中实现自定义格式的转换;程序中解析到JSON func (t MyTime) MarshalJSON() ([]byte, error) { formatted := fmt.Sprintf("\"%s\"", t.Format(formatTime)) return []byte(formatted), nil } //JSON中解析到程序中 func (t *MyTime) UnmarshalJSON(data []byte) (err error) { now, err := time.ParseInLocation(`"` timeFormart `"`, string(data), time.Local) *t = MyTime{Time: now} return } //写入数据库时会调用该方法将自定义时间类型转换并写入数据库 func (t MyTime) Value() (driver.Value, error) { var zeroTime time.Time if t.Time.UnixNano() == zeroTime.UnixNano() { return nil, nil } return t.Time, nil } //读取数据库时会调用该方法将时间数据转换成自定义时间类型 func (t *MyTime) Scan(v interface{}) error { value, ok := v.(time.Time) if ok { *t = MyTime{Time: value} return nil } return fmt.Errorf("can not convert %v to timestamp", v) } //钩子函数 func (v BaseModel) BeforeCreate(scope *gorm.Scope) error { scope.SetColumn("created_at", time.Now()) scope.SetColumn("updated_at", time.Now()) return nil } //钩子函数 func (v BaseModel) BeforeUpdate(scope *gorm.Scope) error { scope.SetColumn("updated_at", time.Now()) return nil }</code></pre>

gorm的hook钩子函数:https://gorm.io/docs/hooks.html

使用,dutils是上面的包。而且也是时间类型。

<pre><code>type MineTime struct { Id int64 `json:"id"` CreatedAt dutils.MyTime `json:"created_at" gorm:"column:created_at"` UpdatedAt dutils.MyTime `json:"updated_at" gorm:"column:updated_at"` }</code></pre>

 结果:

这样就可以保证时间格式都是标准的格式了,而且会自动创建,更新时间。

参考博客:

https://www.cnblogs.com/mrylong/p/11326792.html

 

到此这篇关于“gorm time.Time 使用钩子函数解决反序列化问题”的文章就介绍到这了,更多文章或继续浏览下面的相关文章,希望大家以后多多支持JQ教程网!

您可能感兴趣的文章:
gorm time.Time 使用钩子函数解决反序列化问题
c# 系统钩子的实现代码
C# Hook钩子实例-截取键盘输入
Golang适用的DTO工具
PHP中钩子的理解与实例教程
python 钩子是什么
php提示Notice:unserialize()[function.unserialize]:Error错误解决办法
python 装饰器详解
php数组编码转换小例子
python灰帽子讲的什么