其实老生常谈了,通过Struct映射数据库与JSON的时候,datetime类型会有各种异常,解决如下:
// Import package
import (
"database/sql/driver"
"fmt"
"strconv"
"time"
)
// 定义一个JSONDate类型
type JSONDate struct {
time.Time
}
// 定义JSON构建与解析函数
func (t JSONDate) MarshalJSON() ([]byte, error) {
formatted := fmt.Sprintf("\"%s\"", t.Format("2006-01-02"))
return []byte(formatted), nil
}
func (t *JSONDate) UnmarshalJSON(data []byte) error {
uq, _ := strconv.Unquote(string(data))
value, err := time.ParseInLocation("2006-01-02", uq, time.Local)
if err == nil {
*t = JSONDate{Time: value}
return nil
}
return err
}
// 定义数据库支持函数
func (t JSONDate) Value() (driver.Value, error) {
var zeroTime time.Time
if t.Time.UnixNano() == zeroTime.UnixNano() {
return nil, nil
}
return t.Time, nil
}
func (t *JSONDate) Scan(v interface{}) error {
value, ok := v.(time.Time)
if ok {
*t = JSONDate{Time: value}
return nil
}
return fmt.Errorf("can not convert %v to timestamp", v)
}
// 定义Model
type User struct {
Date JSONDate `json:"date"`
}
还遇到一个问题,关于货币类型的数据,在数据库中一般是以decimal类型存储,有时也会乘以100或者10000以integer存储。而在gorm中,因为float的长度和精度问题,不能满足需求,经过各种弯路,找到一个相对靠谱的方法:
import "github.com/shopspring/decimal"
type Bill struct {
Amount decimal.Decimal `gorm:"type:decimal(10,2)" json:"amount,string"`
}