// Package validator ... // // Description : validator ... // // Author : go_developer@163.com<白茶清欢> // // Date : 2024-05-01 22:32 package validator import ( "fmt" "git.zhangdeman.cn/gateway/validator/define" "git.zhangdeman.cn/zhangdeman/consts" "git.zhangdeman.cn/zhangdeman/serialize" "git.zhangdeman.cn/zhangdeman/util" "github.com/tidwall/gjson" "reflect" "strings" ) // handleSliceInt ... // // Author : go_developer@163.com<白茶清欢> // // Date : 22:30 2024/4/30 func handleSliceInt(inputValue interface{}, rule *define.FieldRule) ([]int64, error) { var ( anySlice []any err error ) if anySlice, err = handleSlice(inputValue, rule); nil != err { return nil, err } intSlice := make([]int64, 0) for _, item := range anySlice { var itemInt int64 if err = util.ConvertAssign(&itemInt, item); nil != err { return nil, fmt.Errorf("%v : data type expect int, but convert fail : %v", rule.Path, err.Error()) } intSlice = append(intSlice, itemInt) } return intSlice, nil } // handleSliceUint ... // // Author : go_developer@163.com<白茶清欢> // // Date : 22:30 2024/4/30 func handleSliceUint(inputValue interface{}, rule *define.FieldRule) ([]uint64, error) { var ( anySlice []any err error ) if anySlice, err = handleSlice(inputValue, rule); nil != err { return nil, err } uintSlice := make([]uint64, 0) for _, item := range anySlice { var itemUint uint64 if err = util.ConvertAssign(&itemUint, item); nil != err { return nil, fmt.Errorf("%v : data type expect uint, but convert fail : %v", rule.Path, err.Error()) } uintSlice = append(uintSlice, itemUint) } return uintSlice, nil } // handleSliceBool ... // // Author : go_developer@163.com<白茶清欢> // // Date : 22:30 2024/4/30 func handleSliceBool(inputValue interface{}, rule *define.FieldRule) ([]bool, error) { var ( anySlice []any err error ) if anySlice, err = handleSlice(inputValue, rule); nil != err { return nil, err } boolSlice := make([]bool, 0) for _, item := range anySlice { var itemBool bool if err = util.ConvertAssign(&itemBool, item); nil != err { return nil, fmt.Errorf("%v : data type expect bool, but convert fail : %v", rule.Path, err.Error()) } boolSlice = append(boolSlice, itemBool) } return boolSlice, nil } // handleSliceFloat ... // // Author : go_developer@163.com<白茶清欢> // // Date : 22:30 2024/4/30 func handleSliceFloat(inputValue interface{}, rule *define.FieldRule) ([]float64, error) { var ( anySlice []any err error ) if anySlice, err = handleSlice(inputValue, rule); nil != err { return nil, err } floatSlice := make([]float64, 0) for _, item := range anySlice { var itemFloat float64 if err = util.ConvertAssign(&itemFloat, item); nil != err { return nil, fmt.Errorf("%v : data type expect float, but convert fail : %v", rule.Path, err.Error()) } floatSlice = append(floatSlice, itemFloat) } return floatSlice, nil } // handleSliceSlice ... // // Author : go_developer@163.com<白茶清欢> // // Date : 22:30 2024/4/30 func handleSliceSlice(inputValue interface{}, rule *define.FieldRule) ([][]any, error) { var ( anySlice []any err error ) if anySlice, err = handleSlice(inputValue, rule); nil != err { return nil, err } sliceSlice := make([][]any, 0) for _, item := range anySlice { byteData := serialize.JSON.MarshalForByte(item) res := make([]any, 0) if err = serialize.JSON.UnmarshalWithNumber(byteData, &res); nil != err { return nil, fmt.Errorf("%v : data type is expect [][]any, but convert fail : %v", rule.Path, err.Error()) } sliceSlice = append(sliceSlice, res) } return sliceSlice, nil } // handleSliceMapAny ... // // Author : go_developer@163.com<白茶清欢> // // Date : 22:30 2024/4/30 func handleSliceMapAny(inputValue interface{}, rule *define.FieldRule) ([]map[any]any, error) { var ( anySlice []any err error ) if anySlice, err = handleSlice(inputValue, rule); nil != err { return nil, err } mapSlice := make([]map[any]any, 0) for _, item := range anySlice { byteData := serialize.JSON.MarshalForByte(item) jsonRes := gjson.ParseBytes(byteData) res := make(map[any]any) jsonRes.ForEach(func(key, value gjson.Result) bool { res[key.Value()] = value.Value() return true }) mapSlice = append(mapSlice, res) } return mapSlice, nil } // handleSliceMapString ... // // Author : go_developer@163.com<白茶清欢> // // Date : 21:33 2024/5/1 func handleSliceMapString(inputValue interface{}, rule *define.FieldRule) ([]map[string]any, error) { var ( anySlice []any err error ) if anySlice, err = handleSlice(inputValue, rule); nil != err { return nil, err } mapSlice := make([]map[string]any, 0) for _, item := range anySlice { byteData := serialize.JSON.MarshalForByte(item) jsonRes := gjson.ParseBytes(byteData) res := make(map[string]any) jsonRes.ForEach(func(key, value gjson.Result) bool { res[key.String()] = value.Value() return true }) mapSlice = append(mapSlice, res) } return mapSlice, nil } // handleSlice 数组处理 // // Author : go_developer@163.com<白茶清欢> // // Date : 21:30 2024/4/30 func handleSlice(inputValue interface{}, rule *define.FieldRule) ([]any, error) { inputValType := reflect.TypeOf(inputValue).Kind() if inputValType != reflect.Slice && inputValType != reflect.String { return nil, fmt.Errorf("%v : data type is expect slice or string, but get %v", rule.Path, inputValType.String()) } if inputValType == reflect.Slice { inputValue = serialize.JSON.MarshalForString(inputValue) // 重置配置 if nil == rule.SliceConfig { rule.SliceConfig = &define.SliceConfig{ Mode: consts.DataSliceModelMarshal, DisableIgnoreEmpty: false, SplitChar: "", } } else { rule.SliceConfig.Mode = consts.DataSliceModelMarshal } } var ( err error anySlice []any ) if inputStr, ok := inputValue.(string); ok { if anySlice, err = handleSliceString(inputStr, rule); nil != err { return nil, err } } if err = validateSlice(anySlice, rule); nil != err { return nil, err } return anySlice, nil } // handleSliceString ... // // Author : go_developer@163.com<白茶清欢> // // Date : 22:06 2024/4/30 func handleSliceString(inputStr string, rule *define.FieldRule) ([]any, error) { if nil == rule.SliceConfig { return nil, fmt.Errorf("%v : data type is slice, but get string", rule.Path) } if rule.SliceConfig.Mode == consts.DataSliceModelReal { return nil, fmt.Errorf("%v : data type expect real slice, but get string", rule.Path) } var ( err error res []any ) if rule.SliceConfig.Mode == consts.DataSliceModelMarshal { // json序列化之后的 if err = serialize.JSON.UnmarshalWithNumber([]byte(inputStr), &res); nil != err { return nil, fmt.Errorf("%v : data type expect marshal slice, but can not convert", rule.Path) } return res, nil } if rule.SliceConfig.Mode == consts.DataSliceModelWithSplitChar { // 指定字符串切割 strArr := strings.Split(inputStr, rule.SliceConfig.SplitChar) res = make([]any, 0) for _, item := range strArr { if !rule.SliceConfig.DisableIgnoreEmpty && len(item) == 0 { // 没禁用忽略空字符串 continue } res = append(res, item) } return res, nil } return nil, fmt.Errorf("%v : data type is slice, but rule mode [%v] is not supported", rule.Path, rule.SliceConfig.Mode) } // validateSlice ... // // Author : go_developer@163.com<白茶清欢> // // Date : 09:39 2024/5/1 func validateSlice(anySlice []any, rule *define.FieldRule) error { // 验证 if nil == rule.ValueLimit { return nil } if nil != rule.ValueLimit.Min && float64(len(anySlice)) < *rule.ValueLimit.Min { return fmt.Errorf("%v : data type is slice, min length is [%v], real length is [%v]", rule.Path, *rule.ValueLimit.Min, len(anySlice)) } if nil != rule.ValueLimit.Max && float64(len(anySlice)) > *rule.ValueLimit.Max { return fmt.Errorf("%v : data type is slice, max length is [%v], real length is [%v]", rule.Path, *rule.ValueLimit.Max, len(anySlice)) } enumTable := make(map[string]bool) for _, item := range rule.ValueLimit.EnumList { enumTable[item] = true } for _, itemVal := range anySlice { if _, exist := enumTable[fmt.Sprintf("%v", itemVal)]; !exist { return fmt.Errorf("%v : data type is slice, slice value [%v] is not un enum list", rule.Path, itemVal) } } return nil }