diff --git a/handle_base.go b/handle_base.go new file mode 100644 index 0000000..e949429 --- /dev/null +++ b/handle_base.go @@ -0,0 +1,139 @@ +// Package validator ... +// +// Description : validator ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2024-05-01 22:34 +package validator + +import ( + "fmt" + "git.zhangdeman.cn/gateway/validator/define" + "git.zhangdeman.cn/zhangdeman/util" + "git.zhangdeman.cn/zhangdeman/wrapper" +) + +// handleFloat 处理float数据 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 15:29 2024/4/29 +func handleFloat(inputVal any, rule *define.FieldRule) (float64, error) { + var ( + err error + formatData float64 + ) + if err = util.ConvertAssign(&formatData, inputVal); nil != err { + return 0, err + } + if !rule.AllowZero { + return 0, fmt.Errorf("%v : field type is float, but zero val is not allowed", rule.Path) + } + if nil == rule.ValueLimit { + return formatData, nil + } + if nil != rule.ValueLimit.Min && formatData < *rule.ValueLimit.Min { + return 0, fmt.Errorf("%v : field type is float, min val is %v, real val is %v", rule.Path, *rule.ValueLimit.Min, formatData) + } + if nil != rule.ValueLimit.Max && formatData > *rule.ValueLimit.Max { + return 0, fmt.Errorf("%v : field type is float, max val is %v, real val is %v", rule.Path, *rule.ValueLimit.Max, formatData) + } + if len(rule.ValueLimit.EnumList) > 0 { + if wrapper.ArrayType(rule.ValueLimit.EnumList).Has(formatData) < 0 { + return 0, fmt.Errorf("%v : field type is float, real val is %v, is not in enum list", rule.Path, formatData) + } + } + return formatData, nil +} + +// handleInt ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 15:36 2024/4/29 +func handleInt(inputVal any, rule *define.FieldRule) (int64, error) { + var ( + err error + formatData int64 + ) + if err = util.ConvertAssign(&formatData, inputVal); nil != err { + return 0, err + } + if _, err = handleFloat(formatData, rule); nil != err { + return 0, err + } + return formatData, nil +} + +// handleUint ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 21:28 2024/4/30 +func handleUint(inputVal any, rule *define.FieldRule) (uint64, error) { + var ( + err error + formatData uint64 + ) + if err = util.ConvertAssign(&formatData, inputVal); nil != err { + return 0, err + } + if _, err = handleFloat(formatData, rule); nil != err { + return 0, err + } + return formatData, nil +} + +// handleBool... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 21:26 2024/4/30 +func handleBool(inputVal any, rule *define.FieldRule) (bool, error) { + var ( + err error + formatData bool + ) + if err = util.ConvertAssign(&formatData, inputVal); nil != err { + return false, err + } + if _, err = handleFloat(formatData, rule); nil != err { + return false, err + } + return formatData, nil +} + +// handleString ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 15:53 2024/4/29 +func handleString(inputVal any, rule *define.FieldRule) (string, error) { + var ( + err error + formatData string + ) + if err = util.ConvertAssign(&formatData, inputVal); nil != err { + return "", err + } + if nil == rule.ValueLimit { + return formatData, nil + } + if nil != rule.ValueLimit.Min { + if float64(len(formatData)) < *rule.ValueLimit.Min { + return "", fmt.Errorf("%v : data type is string, min length is %v, real length is %v", rule.Path, *rule.ValueLimit.Min, len(formatData)) + } + } + if nil != rule.ValueLimit.Max { + if float64(len(formatData)) >= *rule.ValueLimit.Max { + return "", fmt.Errorf("%v : data type is string, max length is %v, real length is %v", rule.Path, *rule.ValueLimit.Max, len(formatData)) + } + } + if len(rule.ValueLimit.EnumList) > 0 { + if wrapper.ArrayType(rule.ValueLimit.EnumList).Has(formatData) < 0 { + return "", fmt.Errorf("%v : data type is string, not in enum list, real val is %v", rule.Path, formatData) + } + } + return formatData, nil +} diff --git a/handle_map.go b/handle_map.go new file mode 100644 index 0000000..d488261 --- /dev/null +++ b/handle_map.go @@ -0,0 +1,178 @@ +// Package validator ... +// +// Description : validator ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2024-05-01 22:33 +package validator + +import ( + "fmt" + "git.zhangdeman.cn/gateway/validator/define" + "git.zhangdeman.cn/zhangdeman/serialize" + "github.com/tidwall/gjson" +) + +// handleMapStringFloat ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 16:38 2024/4/29 +func handleMapStringFloat(inputVal any, rule *define.FieldRule) (map[string]float64, error) { + var ( + err error + res map[string]float64 + ) + + if err = strOrMapConvert(inputVal, &res); nil != err { + return nil, err + } + + dataFieldTable := make(map[string]string) + for k, _ := range res { + dataFieldTable[k] = k + } + + if err = validateMap(dataFieldTable, rule); nil != err { + return nil, err + } + + return res, nil +} + +// handleMapStringAny ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 17:19 2024/4/29 +func handleMapStringAny(inputVal any, rule *define.FieldRule) (map[string]any, error) { + var ( + err error + res map[string]any + ) + + if err = strOrMapConvert(inputVal, &res); nil != err { + return nil, err + } + + dataFieldTable := make(map[string]string) + for k, _ := range res { + dataFieldTable[k] = k + } + + if err = validateMap(dataFieldTable, rule); nil != err { + return nil, err + } + + return res, nil +} + +// handleMapStringSlice... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 17:42 2024/4/29 +func handleMapStringSlice(inputVal any, rule *define.FieldRule) (map[string][]any, error) { + var ( + err error + res map[string][]any + ) + + if err = strOrMapConvert(inputVal, &res); nil != err { + return nil, err + } + + dataFieldTable := make(map[string]string) + for k, _ := range res { + dataFieldTable[k] = k + } + + if err = validateMap(dataFieldTable, rule); nil != err { + return nil, err + } + + return res, nil +} + +// handleMapAnyAny map[any]any处理 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 17:33 2024/4/29 +func handleMapAnyAny(inputVal any, rule *define.FieldRule) (map[any]any, error) { + var ( + err error + res = map[any]any{} + jsonRes gjson.Result + ) + + if inputValStr, ok := inputVal.(string); ok { + jsonRes = gjson.Parse(inputValStr) + } else { + jsonRes = gjson.Parse(serialize.JSON.MarshalForString(inputVal)) + } + + if !jsonRes.IsObject() { + return nil, fmt.Errorf("%v : is not a map", rule.Path) + } + fieldTable := make(map[string]string) + jsonRes.ForEach(func(key, value gjson.Result) bool { + fieldTable[key.String()] = key.String() + res[key.Value()] = value.Value() + return true + }) + if err = validateMap(fieldTable, rule); nil != err { + return nil, err + } + + return res, nil +} + +// strOrMapConvert 字符串或map转map +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 17:26 2024/4/29 +func strOrMapConvert(inputVal any, receiver any) error { + var ( + err error + ) + + if inputValStr, ok := inputVal.(string); ok { + if err = serialize.JSON.UnmarshalWithNumber([]byte(inputValStr), receiver); nil != err { + return err + } + } else { + byteData := serialize.JSON.MarshalForByte(inputVal) + if err = serialize.JSON.UnmarshalWithNumber(byteData, receiver); nil != err { + return err + } + } + return nil +} + +// validateMap 验证map数据 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 17:21 2024/4/29 +func validateMap(dataFieldTable map[string]string, rule *define.FieldRule) error { + if nil == rule.ValueLimit { + return nil + } + if nil != rule.ValueLimit.Min && float64(len(dataFieldTable)) < *rule.ValueLimit.Min { + return fmt.Errorf("%v : data type is map, min item cnt is %v, real item cnt is %v", rule.Path, *rule.ValueLimit.Min, len(dataFieldTable)) + } + if nil != rule.ValueLimit.Max && float64(len(dataFieldTable)) >= *rule.ValueLimit.Max { + return fmt.Errorf("%v : data type is map, max item cnt is %v, real item max is %v", rule.Path, *rule.ValueLimit.Max, len(dataFieldTable)) + } + if nil != rule.ValueLimit.Map { + for _, itemField := range rule.ValueLimit.Map.IncludeFieldList { + if _, exist := dataFieldTable[itemField]; !exist { + return fmt.Errorf("%v : data type is map, %v field is required, but not found", rule.Path, itemField) + } + } + } + return nil +} diff --git a/handle_slice.go b/handle_slice.go new file mode 100644 index 0000000..6f0859d --- /dev/null +++ b/handle_slice.go @@ -0,0 +1,305 @@ +// 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, + DisableAutoConvert: 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) + } + if rule.SliceConfig.Mode == consts.DataSliceModelMarshal { // json序列化之后的 + var ( + err error + res []any + ) + 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) + anyArr := make([]any, 0) + for _, item := range strArr { + if !rule.SliceConfig.DisableIgnoreEmpty && len(item) == 0 { + // 没禁用忽略空字符串 + continue + } + anyArr = append(anyArr, item) + } + return anyArr, 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.Min { + 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 +} diff --git a/run.go b/run.go index 55ab1e2..ec022f6 100644 --- a/run.go +++ b/run.go @@ -13,12 +13,8 @@ import ( "fmt" "git.zhangdeman.cn/gateway/validator/define" "git.zhangdeman.cn/zhangdeman/consts" - "git.zhangdeman.cn/zhangdeman/serialize" - "git.zhangdeman.cn/zhangdeman/util" - "git.zhangdeman.cn/zhangdeman/wrapper" "github.com/tidwall/gjson" "github.com/tidwall/sjson" - "reflect" "strings" ) @@ -189,576 +185,3 @@ func handleData(inputVal any, rule *define.FieldRule) (any, error) { } return nil, fmt.Errorf("%v : data type [%v] is not support", rule.Path, rule.Type) } - -// handleFloat 处理float数据 -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 15:29 2024/4/29 -func handleFloat(inputVal any, rule *define.FieldRule) (float64, error) { - var ( - err error - formatData float64 - ) - if err = util.ConvertAssign(&formatData, inputVal); nil != err { - return 0, err - } - if !rule.AllowZero { - return 0, fmt.Errorf("%v : field type is float, but zero val is not allowed", rule.Path) - } - if nil == rule.ValueLimit { - return formatData, nil - } - if nil != rule.ValueLimit.Min && formatData < *rule.ValueLimit.Min { - return 0, fmt.Errorf("%v : field type is float, min val is %v, real val is %v", rule.Path, *rule.ValueLimit.Min, formatData) - } - if nil != rule.ValueLimit.Max && formatData > *rule.ValueLimit.Max { - return 0, fmt.Errorf("%v : field type is float, max val is %v, real val is %v", rule.Path, *rule.ValueLimit.Max, formatData) - } - if len(rule.ValueLimit.EnumList) > 0 { - if wrapper.ArrayType(rule.ValueLimit.EnumList).Has(formatData) < 0 { - return 0, fmt.Errorf("%v : field type is float, real val is %v, is not in enum list", rule.Path, formatData) - } - } - return formatData, nil -} - -// handleInt ... -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 15:36 2024/4/29 -func handleInt(inputVal any, rule *define.FieldRule) (int64, error) { - var ( - err error - formatData int64 - ) - if err = util.ConvertAssign(&formatData, inputVal); nil != err { - return 0, err - } - if _, err = handleFloat(formatData, rule); nil != err { - return 0, err - } - return formatData, nil -} - -// handleUint ... -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 21:28 2024/4/30 -func handleUint(inputVal any, rule *define.FieldRule) (uint64, error) { - var ( - err error - formatData uint64 - ) - if err = util.ConvertAssign(&formatData, inputVal); nil != err { - return 0, err - } - if _, err = handleFloat(formatData, rule); nil != err { - return 0, err - } - return formatData, nil -} - -// handleBool... -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 21:26 2024/4/30 -func handleBool(inputVal any, rule *define.FieldRule) (bool, error) { - var ( - err error - formatData bool - ) - if err = util.ConvertAssign(&formatData, inputVal); nil != err { - return false, err - } - if _, err = handleFloat(formatData, rule); nil != err { - return false, err - } - return formatData, nil -} - -// handleString ... -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 15:53 2024/4/29 -func handleString(inputVal any, rule *define.FieldRule) (string, error) { - var ( - err error - formatData string - ) - if err = util.ConvertAssign(&formatData, inputVal); nil != err { - return "", err - } - if nil == rule.ValueLimit { - return formatData, nil - } - if nil != rule.ValueLimit.Min { - if float64(len(formatData)) < *rule.ValueLimit.Min { - return "", fmt.Errorf("%v : data type is string, min length is %v, real length is %v", rule.Path, *rule.ValueLimit.Min, len(formatData)) - } - } - if nil != rule.ValueLimit.Max { - if float64(len(formatData)) >= *rule.ValueLimit.Max { - return "", fmt.Errorf("%v : data type is string, max length is %v, real length is %v", rule.Path, *rule.ValueLimit.Max, len(formatData)) - } - } - if len(rule.ValueLimit.EnumList) > 0 { - if wrapper.ArrayType(rule.ValueLimit.EnumList).Has(formatData) < 0 { - return "", fmt.Errorf("%v : data type is string, not in enum list, real val is %v", rule.Path, formatData) - } - } - return formatData, nil -} - -// handleMapStringFloat ... -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 16:38 2024/4/29 -func handleMapStringFloat(inputVal any, rule *define.FieldRule) (map[string]float64, error) { - var ( - err error - res map[string]float64 - ) - - if err = strOrMapConvert(inputVal, &res); nil != err { - return nil, err - } - - dataFieldTable := make(map[string]string) - for k, _ := range res { - dataFieldTable[k] = k - } - - if err = validateMap(dataFieldTable, rule); nil != err { - return nil, err - } - - return res, nil -} - -// handleMapStringAny ... -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 17:19 2024/4/29 -func handleMapStringAny(inputVal any, rule *define.FieldRule) (map[string]any, error) { - var ( - err error - res map[string]any - ) - - if err = strOrMapConvert(inputVal, &res); nil != err { - return nil, err - } - - dataFieldTable := make(map[string]string) - for k, _ := range res { - dataFieldTable[k] = k - } - - if err = validateMap(dataFieldTable, rule); nil != err { - return nil, err - } - - return res, nil -} - -// handleMapStringSlice... -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 17:42 2024/4/29 -func handleMapStringSlice(inputVal any, rule *define.FieldRule) (map[string][]any, error) { - var ( - err error - res map[string][]any - ) - - if err = strOrMapConvert(inputVal, &res); nil != err { - return nil, err - } - - dataFieldTable := make(map[string]string) - for k, _ := range res { - dataFieldTable[k] = k - } - - if err = validateMap(dataFieldTable, rule); nil != err { - return nil, err - } - - return res, nil -} - -// handleMapAnyAny map[any]any处理 -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 17:33 2024/4/29 -func handleMapAnyAny(inputVal any, rule *define.FieldRule) (map[any]any, error) { - var ( - err error - res = map[any]any{} - jsonRes gjson.Result - ) - - if inputValStr, ok := inputVal.(string); ok { - jsonRes = gjson.Parse(inputValStr) - } else { - jsonRes = gjson.Parse(serialize.JSON.MarshalForString(inputVal)) - } - - if !jsonRes.IsObject() { - return nil, fmt.Errorf("%v : is not a map", rule.Path) - } - fieldTable := make(map[string]string) - jsonRes.ForEach(func(key, value gjson.Result) bool { - fieldTable[key.String()] = key.String() - res[key.Value()] = value.Value() - return true - }) - if err = validateMap(fieldTable, rule); nil != err { - return nil, err - } - - return res, nil -} - -// strOrMapConvert 字符串或map转map -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 17:26 2024/4/29 -func strOrMapConvert(inputVal any, receiver any) error { - var ( - err error - ) - - if inputValStr, ok := inputVal.(string); ok { - if err = serialize.JSON.UnmarshalWithNumber([]byte(inputValStr), receiver); nil != err { - return err - } - } else { - byteData := serialize.JSON.MarshalForByte(inputVal) - if err = serialize.JSON.UnmarshalWithNumber(byteData, receiver); nil != err { - return err - } - } - return nil -} - -// validateMap 验证map数据 -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 17:21 2024/4/29 -func validateMap(dataFieldTable map[string]string, rule *define.FieldRule) error { - if nil == rule.ValueLimit { - return nil - } - if nil != rule.ValueLimit.Min && float64(len(dataFieldTable)) < *rule.ValueLimit.Min { - return fmt.Errorf("%v : data type is map, min item cnt is %v, real item cnt is %v", rule.Path, *rule.ValueLimit.Min, len(dataFieldTable)) - } - if nil != rule.ValueLimit.Max && float64(len(dataFieldTable)) >= *rule.ValueLimit.Max { - return fmt.Errorf("%v : data type is map, max item cnt is %v, real item max is %v", rule.Path, *rule.ValueLimit.Max, len(dataFieldTable)) - } - if nil != rule.ValueLimit.Map { - for _, itemField := range rule.ValueLimit.Map.IncludeFieldList { - if _, exist := dataFieldTable[itemField]; !exist { - return fmt.Errorf("%v : data type is map, %v field is required, but not found", rule.Path, itemField) - } - } - } - return nil -} - -// 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, - DisableAutoConvert: 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) - } - if rule.SliceConfig.Mode == consts.DataSliceModelMarshal { // json序列化之后的 - var ( - err error - res []any - ) - 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) - anyArr := make([]any, 0) - for _, item := range strArr { - if !rule.SliceConfig.DisableIgnoreEmpty && len(item) == 0 { - // 没禁用忽略空字符串 - continue - } - anyArr = append(anyArr, item) - } - return anyArr, 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.Min { - 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 -}