fox/mapstruct/options.go

108 lines
3.0 KiB
Go
Raw Normal View History

package mapstruct
import (
"fmt"
"reflect"
"time"
)
// HookFunc 定义字段转换钩子函数类型
type HookFunc func(reflect.Value, reflect.StructField) (any, error)
// StringHookFunc 定义字符串到值的转换钩子函数类型
type StringHookFunc func(string, reflect.StructField) (any, error)
// Options 包含所有转换选项
type Options struct {
TagName string // 使用的结构体标签名称
TypeHooks map[reflect.Type]HookFunc // 类型级别的钩子
StringTypeHooks map[reflect.Type]StringHookFunc // 字符串到类型的钩子
FieldHooks map[string]HookFunc // 字段级别的钩子
}
// Option 是配置选项的函数类型
type Option func(*Options)
// WithTagName 设置结构体标签名称
func WithTagName(name string) Option {
return func(o *Options) {
o.TagName = name
}
}
// WithTypeHook 添加类型级别的转换钩子
func WithTypeHook(typ reflect.Type, hook HookFunc) Option {
return func(o *Options) {
if o.TypeHooks == nil {
o.TypeHooks = make(map[reflect.Type]HookFunc)
}
o.TypeHooks[typ] = hook
}
}
// WithStringTypeHook 添加字符串到类型的转换钩子
func WithStringTypeHook(typ reflect.Type, hook StringHookFunc) Option {
return func(o *Options) {
if o.StringTypeHooks == nil {
o.StringTypeHooks = make(map[reflect.Type]StringHookFunc)
}
o.StringTypeHooks[typ] = hook
}
}
// WithFieldHook 添加字段级别的转换钩子
func WithFieldHook(fieldName string, hook HookFunc) Option {
return func(o *Options) {
if o.FieldHooks == nil {
o.FieldHooks = make(map[string]HookFunc)
}
o.FieldHooks[fieldName] = hook
}
}
//// WithStringFieldHook 添加字段级别的字符串转换钩子
//func WithStringFieldHook(fieldName string, hook StringHookFunc) Option {
// return func(o *Options) {
// if o.FieldHooks == nil {
// o.FieldHooks = make(map[string]HookFunc)
// }
// // 适配器将StringHookFunc转换为HookFunc
// o.FieldHooks[fieldName] = func(v reflect.Value, f reflect.StructField) (any, error) {
// if v.Kind() != reflect.String {
// return nil, nil
// }
// return hook(v.String(), f)
// }
// }
//}
// defaultOptions 返回默认配置选项
func defaultOptions() *Options {
opts := &Options{
TagName: "json", // 默认使用json标签
}
// 注册默认的时间类型钩子
WithStringTypeHook(reflect.TypeOf(time.Time{}), func(value string, _ reflect.StructField) (any, error) {
// 尝试多种常见时间格式
formats := []string{
"2006-01-02 15:04:05", // 标准格式
"2006-01-02", // 仅日期
time.RFC3339, // ISO8601格式
"2006/01/02 15:04:05", // 斜杠分隔
"2006/01/02", // 斜杠分隔仅日期
"02-Jan-2006", // 英文月份缩写
}
for _, layout := range formats {
if t, err := time.Parse(layout, value); err == nil {
return t, nil
}
}
return nil, fmt.Errorf("无法解析时间字符串: %s", value)
})(opts)
return opts
}