在使用iris的时候
我们有这么一个结构体
type BannersCreateOrUpdate struct {
Id int `json:"id" validate:"numeric"`
Title string `json:"title" validate:"required"`
StartTime time.Time `json:"start_time" form:"start_time"`
}
我们有一个start_time的字段,如果前端希望传入2019-08-01 11:11:11
时,如果使用c.Ctx.ReadForm(&p)
的方式来获取,则获取不到正确的时间,报错如下schema: error converting value for "start_time". Details: parsing time "2019-08-01 11:11:11" as "2006-01-02T15:04:05Z07:00": cannot parse " 11:11:11" as "T"
所以这里就会涉及到自定义解析器,类似json的做法.
查看iris的源码,这里使用一个map来存储类型和Converter的map,解析时就通过这个来查找并调用对应的转换器,也提供了一个注册方法来添加转换器,不过由于被封装了formDecoder = NewDecoder()
,小写的变量没法直接访问。
type Converter func(string) reflect.Value
// RegisterConverter registers a converter function for a custom type.
func (d *Decoder) RegisterConverter(value interface{}, converterFunc Converter) {
d.cache.registerConverter(value, converterFunc)
}
刚好可以直接go:linkname,强行获取formDecoder
,从而添加注册器。
- 需要引入
_ "unsafe"
包 - 添加注释,将schema下的formDecoder链接到这里.
//go:linkname formDecoder github.com/iris-contrib/schema.formDecoder
- 将
StartTime
的类型换成自定义的NormalTime
类型
实现源码:
package common
import (
"github.com/iris-contrib/schema"
_ "github.com/iris-contrib/schema"
"reflect"
"time"
_ "unsafe"
)
//go:linkname formDecoder github.com/iris-contrib/schema.formDecoder
//go:nosplit
var formDecoder *schema.Decoder
type NormalTime time.Time
func (n NormalTime) Converter(s string) reflect.Value {
if t, err := time.Parse("2006-01-02 15:04:05", s); err == nil {
return reflect.ValueOf(NormalTime(t))
}
return reflect.Value{}
}
func RegisterNormalTimeDecoder() {
var nt = NormalTime{}
formDecoder.RegisterConverter(nt, nt.Converter)
}
最后在main.go
中或者合适的地方调用RegisterNormalTimeDecoder()
即可
网友评论