在 Golang 中,时间的默认序列化格式是 RFC3339。由于使用标准库中的 time.Time
类型,开发者在处理 JSON 时可能会希望使用不同的格式。本文将介绍如何在 Golang 中自定义 time.Time
类型字段的 JSON 序列化格式,并在 Gorm 中自定义 JSON 时间字段格式。
Golang 中时间格式的定义
Golang 中的时间格式通过常量进行定义,最常用的格式包括:
const (
RFC3339 = "2006-01-02T15:04:05Z07:00"
// 其他格式省略
)
默认的 JSON 序列化格式
当 Golang 将包含 time.Time
类型字段的结构体序列化为 JSON 时,默认使用 RFC3339 格式。例如,序列化后的时间格式通常为 2006-01-02T15:04:05Z07:00
。这种格式在处理大多数时间相关的应用中是足够的,但在某些场景下,开发者可能需要更具可读性的格式,如 2006-01-02 15:04:05
。
Golang 如何实现自定义时间序列化格式
为了自定义 time.Time
类型字段的 JSON 序列化格式,需要重写 json.Marshaler
接口。由于 Go 不允许在包外定义方法,我们需要通过别名或内嵌结构体的方式实现这一点。
别名方式(不推荐)
type JSONTime time.Time
内嵌方式(推荐)
type JSONTime struct {
time.Time
}
// MarshalJSON 覆盖 time.Time 的 MarshalJSON
func (t JSONTime) MarshalJSON() ([]byte, error) {
formatted := fmt.Sprintf("\"%s\"", t.Format("2006-01-02 15:04:05"))
return []byte(formatted), nil
}
使用内嵌方式的优点是可以直接访问 time.Time
的方法和字段。
示例代码
以下是一个完整的示例,展示了如何使用自定义的 JSONTime
类型:
package main
import (
"encoding/json"
"fmt"
"time"
)
type MyStruct struct {
CreatedAt time.Time
}
type JSONTime struct {
time.Time
}
// MarshalJSON 覆盖 time.Time 的 MarshalJSON
func (t JSONTime) MarshalJSON() ([]byte, error) {
formatted := fmt.Sprintf("\"%s\"", t.Format("2006-01-02 15:04:05"))
return []byte(formatted), nil
}
type MyStruct2 struct {
CreatedAt JSONTime
}
func main() {
ms := MyStruct{
CreatedAt: time.Now(),
}
m, _ := json.Marshal(ms)
fmt.Println("time.Time: ", string(m))
ms2 := MyStruct2{
CreatedAt: JSONTime{time.Now()},
}
m2, _ := json.Marshal(ms2)
fmt.Println("JSONTime: ", string(m2))
}
输出结果
time.Time: {"CreatedAt":"2009-11-10T23:00:00Z"}
JSONTime: {"CreatedAt":"2009-11-10 23:00:00"}
自定义 Gorm Model 中 time.Time
类型字段的 JSON 序列化格式
在 Gorm 中,要自定义时间字段的 JSON 序列化格式,除了重写 MarshalJSON
方法外,还需实现 database/sql
中的 Value
和 Scan
方法,以确保与数据库的交互正常。
完整实现示例
package main
import (
"database/sql/driver"
"fmt"
"time"
)
type JSONTime struct {
time.Time
}
// MarshalJSON 自定义时间格式
func (t JSONTime) MarshalJSON() ([]byte, error) {
formatted := fmt.Sprintf("\"%s\"", t.Format("2006-01-02 15:04:05"))
return []byte(formatted), nil
}
// Value 实现 database/sql 的驱动接口
func (t JSONTime) Value() (driver.Value, error) {
if t.Time.IsZero() {
return nil, nil
}
return t.Time, nil
}
// Scan 从数据库读取时间值
func (t *JSONTime) Scan(v interface{}) error {
value, ok := v.(time.Time)
if ok {
*t = JSONTime{Time: value}
return nil
}
return fmt.Errorf("cannot convert %v to timestamp", v)
}
// BaseModel 用于 Gorm 模型的时间字段
type BaseModel struct {
ID int `gorm:"primary_key" json:"id"`
CreatedAt JSONTime `json:"createdAt"`
UpdatedAt JSONTime `json:"updatedAt"`
DeletedAt JSONTime `gorm:"index" json:"-"`
}
在定义 Gorm 模型时,只需将时间字段使用自定义的 JSONTime
类型即可。
相关阅读推荐:Golang JSON 操作完全指南:从基础到进阶,看这一篇就够了!
总结
自定义 Golang 中 time.Time
类型字段的 JSON 序列化格式可以通过实现 MarshalJSON
方法以及与 Gorm 的数据库交互功能来完成。通过灵活使用内嵌结构体,开发者能够轻松实现所需的时间格式,提升 API 的可读性和用户体验。