From d9a775a799483b71778e5fc43b45cafa6a8783af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Tue, 30 Apr 2024 22:22:28 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0slice=E7=9A=84=E5=85=AC?= =?UTF-8?q?=E5=85=B1=E9=80=BB=E8=BE=91=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- define/rule.go | 12 ++++++ go.mod | 2 +- go.sum | 2 + run.go | 108 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 123 insertions(+), 1 deletion(-) diff --git a/define/rule.go b/define/rule.go index d7d10af..ef37090 100644 --- a/define/rule.go +++ b/define/rule.go @@ -23,6 +23,7 @@ type FieldRule struct { AllowNil bool `json:"allow_nil"` // 必传时, nil值是否合法 RequiredConditionGroup [][]RequiredCondition `json:"required_condition_group"` // 满足何种条件,字段必传,不配置则为无差别必传, 组之间是或条件, 满足一组即命中, 组之内为与条件 ValueLimit *ValueLimit `json:"value_limit"` // 数据值的限制 + SliceConfig *SliceConfig `json:"slice_config"` // 数组转化的配置 } // RequiredCondition 定义必传条件 @@ -66,3 +67,14 @@ type StringValueLimit struct { type MapValueLimit struct { IncludeFieldList []string `json:"include_field_list"` // 必须存在的字段列表 } + +// SliceConfig slice的配置 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 21:34 2024/4/30 +type SliceConfig struct { + Mode string `json:"slice_mode"` // REAL - 输入直接是slice MARSHAL - json序列化之后的字符串 WITH_SPLIT_CHAR - 使用指定字符串分隔 + DisableAutoConvert bool `json:"disable_auto_convert"` // 禁用自动格式转换, 不禁用情况下, ["1","2","3"] 可以转换成 [1,2,3] + SplitChar string `json:"split_char"` // 数组转换的分隔符, 当输入模式是 WITH_SPLIT_CHAR 时生效 +} diff --git a/go.mod b/go.mod index 69f2923..e06d336 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module git.zhangdeman.cn/gateway/validator go 1.22.2 require ( - git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240429082641-eeef7e967d00 // indirect + git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240430135109-0be82b4a6434 // indirect git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240311030808-e2a2e6a3c211 // indirect git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240325080031-1f58204e8687 // indirect git.zhangdeman.cn/zhangdeman/util v0.0.0-20231227095334-7eb5cdbf9253 // indirect diff --git a/go.sum b/go.sum index 55fd107..cbcf844 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240429080251-9cd57471a8f5 h1:6JsrAD git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240429080251-9cd57471a8f5/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k= git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240429082641-eeef7e967d00 h1:bOPZXYX9CfnZBPqkQnzgwnuC1uyXBivSY0nmV4HabXg= git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240429082641-eeef7e967d00/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k= +git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240430135109-0be82b4a6434 h1:BgpbeE3Vuy1iS4xrMzJP6bDGbrrhlv8uSDh8n/Sj+fg= +git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240430135109-0be82b4a6434/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k= git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240311030808-e2a2e6a3c211 h1:I/wOsRpCSRkU9vo1u703slQsmK0wnNeZzsWQOGtIAG0= git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240311030808-e2a2e6a3c211/go.mod h1:SrtvrQRdzt+8KfYzvosH++gWxo2ShPTzR1m3VQ6uX7U= git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240325080031-1f58204e8687 h1:uQcGqdzi4UdpZlp4f4FUPeBqoygP58pEKJkmN3ROsE0= diff --git a/run.go b/run.go index 7ef8887..e92fa98 100644 --- a/run.go +++ b/run.go @@ -18,6 +18,7 @@ import ( "git.zhangdeman.cn/zhangdeman/wrapper" "github.com/tidwall/gjson" "github.com/tidwall/sjson" + "reflect" "strings" ) @@ -155,8 +156,12 @@ func handleData(inputVal any, rule *define.FieldRule) (any, error) { return handleFloat(inputVal, rule) case consts.DataTypeInt: // int类型 return handleInt(inputVal, rule) + case consts.DataTypeUint: + return handleUint(inputVal, rule) case consts.DataTypeString: // 字符串处理 return handleString(inputVal, rule) + case consts.DataTypeBool: + return handleBool(inputVal, rule) case consts.DataTypeMapStrFloat, consts.DataTypeMapStrBool, consts.DataTypeMapStrInt, consts.DataTypeMapStrUint: // 一律按照 map[string]float64处理 @@ -167,6 +172,8 @@ func handleData(inputVal any, rule *define.FieldRule) (any, error) { return handleMapStringSlice(inputVal, rule) case consts.DataTypeMapAnyAny: // 任意类型map return handleMapAnyAny(inputVal, rule) + case consts.DataTypeSliceUint, consts.DataTypeSliceUintWithChar: // uint数组处理 + } return nil, nil } @@ -223,6 +230,44 @@ func handleInt(inputVal any, rule *define.FieldRule) (int64, error) { 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 0, err + } + if _, err = handleFloat(formatData, rule); nil != err { + return false, err + } + return formatData, nil +} + // handleString ... // // Author : go_developer@163.com<白茶清欢> @@ -419,3 +464,66 @@ func validateMap(dataFieldTable map[string]string, rule *define.FieldRule) error } return 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, + DisableAutoConvert: false, + SplitChar: "", + } + } else { + rule.SliceConfig.Mode = consts.DataSliceModelMarshal + } + } + if inputStr, ok := inputValue.(string); ok { + return handleSliceString(inputStr, rule) + } + + return nil, fmt.Errorf("%v : data type is expect slice or string, but get %v", rule.Path, inputValType.String()) +} + +// 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 { + 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) +}