我正在尝试将时间戳添加到数据库,并让返回的json带有代表时间戳的数字,而不是时间戳的当前字符串表示形式;本质上是覆盖time.Time
的元帅
type JSONTime time.Time
func (j *JSONTime) UnmarshalJSON(data []byte) error {
if string(data) == "null" {
return nil
}
millis, err := strconv.ParseInt(string(data), 10, 64)
if err != nil {
return err
}
*j = JSONTime(time.Unix(0, millis*int64(time.Millisecond)))
return err
}
func (t JSONTime) MarshalJSON() ([]byte, error) {
//do your serializing here
stamp := fmt.Sprintf("%d", time.Time(t).Unix()*1000)
return []byte(stamp), nil
}
type table struct {
ID int64 `gorm:"primary_key;auto_increment"json:"id"`
CreatedAt JSONTime json:"createdAt"`
UpdatedAt JSONTime json:"updatedAt"`
}
我上面的代码存在的问题只是忽略了数据库中列的创建(创建了其他字段)。我什至手动创建了该列,但gorm也不添加数据。
我相信编组和非编组的工作,但是问题甚至出现在使用它们之前(即,将列添加到db)
我在这里做什么错了?
更新1:
以前,我的表结构如下:
type table struct {
ID int64 `gorm:"primary_key;auto_increment"json:"id"`
CreatedAt time.Time json:"createdAt"`
UpdatedAt time.Time json:"updatedAt"`
}
这主要是有效的(例如,在数据库上创建列)
在数据库连接方面,我基本上使用:
root:password@tcp(127.0.0.1:3306)/database?parseTime=true
并对我的仓库使用自动迁移:
db,err := // get db connection
if err != nil {
panic("Failed to connect to database")
}
db.AutoMigrate(&table{})
答案 0 :(得分:1)
由于@mkopriva,我终于弄清楚了。
有几个问题:
1- MarshalJSONand
UnmarshalJSON
仅适用于数据库交互之前和之后
2-结构table
的定义没有正确的gorm
定义:
type tablestruct {
ID int64 `gorm:"primary_key;auto_increment"json:"id"`
CreatedAt timeLib.JSONTime `gorm:"type:timestamp;default:current_timestamp"json:"createdAt"`
UpdatedAt timeLib.JSONTime `gorm:"type:timestamp;default:current_timestamp ON update current_timestamp"json:"updatedAt"`
}
3-由于类型JSONTime
是新类型,驱动程序不知道如何转换它,因此我们需要覆盖Value
:
func (jsonTime JSONTime) Value() (driver.Value, error) {
return time.Time(jsonTime), nil
}
4-最后,我们需要重写Scan
才能将数据库值转换为JSONTime
值
func (jsonTime *JSONTime) Scan(value interface{}) error {
if value == nil {
*jsonTime = JSONTime(time.Now())
return nil
}
if readTime, err := driver.DefaultParameterConverter.ConvertValue(value); err == nil {
if convertedTime, ok := readTime.(time.Time); ok {
*jsonTime = JSONTime(convertedTime)
return nil
}
}
return errors.New("failed to scan TIME")
}