Echo框架如何将yyyy-MM-dd格式日期字符串绑定到含time.Time的结构体
问题原因
Go标准库time.Time默认的JSON/表单反序列化仅支持带时分秒和时区的RFC3339格式(如2006-01-02T15:04:05Z07:00),你传入的2021-09-27纯日期格式不符合默认解析规则,因此需要自定义时间类型实现对应的反序列化接口适配场景。
解决方案
1. 定义自定义日期类型
新建自定义日期类型,实现Echo绑定需要的JSON、表单反序列化方法,按需补充序列化、GORM适配方法:
package model import ( "time" "database/sql/driver" // 适配GORM需要导入该包 ) // CustomDate 自定义支持yyyy-MM-dd格式的日期类型 type CustomDate time.Time // UnmarshalJSON 实现JSON反序列化接口,适配JSON请求 func (d *CustomDate) UnmarshalJSON(data []byte) error { if len(data) == 2 && string(data) == `""` { *d = CustomDate(time.Time{}) return nil } // 如需UTC时区替换time.Local为time.UTC即可 t, err := time.ParseInLocation(`"2006-01-02"`, string(data), time.Local) if err != nil { return err } *d = CustomDate(t) return nil } // UnmarshalForm 实现表单反序列化接口,适配form-data/urlencoded请求 func (d *CustomDate) UnmarshalForm(value string) error { if value == "" { *d = CustomDate(time.Time{}) return nil } t, err := time.ParseInLocation("2006-01-02", value, time.Local) if err != nil { return err } *d = CustomDate(t) return nil } // MarshalJSON 可选:实现JSON序列化,返回响应时也输出yyyy-MM-dd格式 func (d CustomDate) MarshalJSON() ([]byte, error) { t := time.Time(d) if t.IsZero() { return []byte(`""`), nil } return []byte(`"` + t.Format("2006-01-02") + `"`), nil } // Value 可选:实现GORM的Value接口,兼容数据库写入 func (d CustomDate) Value() (driver.Value, error) { t := time.Time(d) if t.IsZero() { return nil, nil } return t, nil } // Scan 可选:实现GORM的Scan接口,兼容数据库读取 func (d *CustomDate) Scan(value interface{}) error { if v, ok := value.(time.Time); ok { *d = CustomDate(v) return nil } return nil }
2. 修改结构体字段类型
把TestModel中Date字段的类型从time.Time替换为自定义的CustomDate:
type TestModel struct { Date CustomDate `json:"date" form:"date" gorm:"index;type:date"` gorm.Model }
3. 原有业务代码无需改动
你之前写的参数绑定逻辑可以直接运行,需要使用标准time.Time类型时强制转换即可:
func CreateDiary(c echo.Context) error { var getData model.TestModel if err := (&echo.DefaultBinder{}).BindBody(c, &getData); err != nil { fmt.Print(err.Error()) return c.JSON(400, map[string]string{"msg": "日期格式错误,请传入yyyy-MM-dd格式"}) } // 转标准time.Time示例:standardTime := time.Time(getData.Date) return c.JSON(200, getData) }
内容的提问来源于stack exchange,提问作者Choi yun seok
相关产品推荐
相关产品推荐

