time.Time 的子类型不使用 gorm 库创建列

sub-type of time.Time doesn't create the Column using gorm lib

我正在尝试向数据库添加时间戳,并让返回的 json 带有代表时间戳的数字,而不是时间戳的当前字符串表示;本质上压倒了 time.Time

的 marshal、unmarshal
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 也没有添加数据。

我相信编组和解组工作,但问题甚至在使用它们之前就存在(即将列添加到数据库)

我做错了什么?

我正在使用 MySQL and library gorm

更新 1:

之前我的 table 结构如下:

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

感谢@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")
}

试一试

type JSONTime struct {
    time.Time
}

type BaseModel struct {
    ID        uint     `gorm:"autoIncrement;primary_key" json:"id"`
    CreatedAt JSONTime `gorm:"type:timestamp;default:current_timestamp" json:"created_at"`
    UpdatedAt JSONTime `gorm:"type:timestamp;default:current_timestamp" json:"updated_at"`
    DeletedAt JSONTime `gorm:"type:timestamp;default:current_timestamp" json:"deleted_at"`
}