基础类型, 无嵌套匿名结构体生成, 待解决寻址问题
This commit is contained in:
		
							
								
								
									
										190
									
								
								validate.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								validate.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,190 @@ | ||||
| // Package validate ... | ||||
| // | ||||
| // Description : validate ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2025-03-18 15:10 | ||||
| package validate | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"git.zhangdeman.cn/zhangdeman/consts" | ||||
| 	"git.zhangdeman.cn/zhangdeman/json_filter/gjson_hack" | ||||
| 	"git.zhangdeman.cn/zhangdeman/serialize" | ||||
| 	"git.zhangdeman.cn/zhangdeman/wrapper" | ||||
| 	"github.com/go-playground/validator/v10" | ||||
| 	"github.com/tidwall/gjson" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| var validatorInstance = validator.New() | ||||
|  | ||||
| // Run 执行参数验证 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 15:12 2025/3/18 | ||||
| func Run(sourceData []byte, fieldList []StructField) ([]byte, error) { | ||||
| 	handleInstance := &handle{ | ||||
| 		sourceData:    sourceData, | ||||
| 		fieldList:     fieldList, | ||||
| 		dynamicStruct: wrapper.NewDynamic(), | ||||
| 	} | ||||
| 	return handleInstance.Run() | ||||
| } | ||||
|  | ||||
| type handle struct { | ||||
| 	sourceData    []byte | ||||
| 	fieldList     []StructField | ||||
| 	dynamicStruct *wrapper.DynamicStruct | ||||
| } | ||||
|  | ||||
| // Run 执行验证 | ||||
| func (h *handle) Run() ([]byte, error) { | ||||
| 	for _, field := range h.fieldList { | ||||
| 		if len(field.Errmsg) == 0 { | ||||
| 			field.Errmsg = field.JsonTag + " : 参数校验不通过" | ||||
| 		} | ||||
| 		required, hasRequired := h.checkRequired(field) | ||||
| 		field.Required = required | ||||
| 		if field.Required && !hasRequired { | ||||
| 			if nil == field.RuleList { | ||||
| 				field.RuleList = make([]Rule, 0) | ||||
| 			} | ||||
| 			field.RuleList = append(field.RuleList, Rule{ | ||||
| 				Tag:  consts.ValidatorRuleCommonRequired.String(), | ||||
| 				Args: nil, | ||||
| 			}) | ||||
| 		} | ||||
| 		sourceValue, err := h.getSourceDataValue(field) | ||||
| 		if nil != err { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		if nil == sourceValue { | ||||
| 			// 没出现异常, 但是value为nil, 视作参数不存在处理 | ||||
| 			continue | ||||
| 		} | ||||
| 		// fieldName := wrapper.String(field.JsonTag).SnakeCaseToCamel() | ||||
| 		h.dynamicStruct.AddAny(field.JsonTag, h.generateTag(field), "dynamic_struct", sourceValue) | ||||
| 	} | ||||
| 	val := h.dynamicStruct.ToStructDefaultValue() | ||||
| 	if err := serialize.JSON.Transition(h.dynamicStruct.MapData(), &val); nil != err { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	targetByte, _ := json.Marshal(val) | ||||
| 	err := validatorInstance.Struct(val) | ||||
| 	return targetByte, err | ||||
| } | ||||
|  | ||||
| // checkRequired 格式化必传参数 | ||||
| // 返回值1, 是否必传 | ||||
| // 返回值2, 校验规则中是否存在必传校验 | ||||
| func (h *handle) checkRequired(field StructField) (bool, bool) { | ||||
| 	required := field.Required | ||||
| 	isHasRequiredRule := false | ||||
| 	for _, rule := range field.RuleList { | ||||
| 		if rule.Tag == consts.ValidatorRuleCommonRequired.String() { | ||||
| 			isHasRequiredRule = true | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 	if isHasRequiredRule { | ||||
| 		required = true | ||||
| 	} | ||||
| 	if required && !isHasRequiredRule { | ||||
| 		// 必传, 但是没有必传校验规则 | ||||
| 		return true, true | ||||
| 	} | ||||
| 	return true, false | ||||
| } | ||||
|  | ||||
| // getSourceDataValue 获取源数据值 | ||||
| func (h *handle) getSourceDataValue(field StructField) (any, error) { | ||||
| 	sourceValue := gjson.GetBytes(h.sourceData, field.SourcePath) | ||||
| 	if !sourceValue.Exists() { | ||||
| 		if field.Required { | ||||
| 			return nil, errors.New(field.SourcePath + " is required") | ||||
| 		} | ||||
| 		if len(field.DefaultValue) > 0 { | ||||
| 			// 非必传, 且设置了默认值, 在数据源不存在时, 这只默认值 | ||||
| 			sourceValue = gjson.Result{ | ||||
| 				Type:    gjson.String, | ||||
| 				Raw:     field.DefaultValue, | ||||
| 				Str:     field.DefaultValue, | ||||
| 				Num:     0, | ||||
| 				Index:   0, | ||||
| 				Indexes: nil, | ||||
| 			} | ||||
| 		} else { | ||||
| 			// 非必传, 且没有默认值, 就当做数据不存在 | ||||
| 			return nil, nil | ||||
| 		} | ||||
| 	} | ||||
| 	switch field.Type { | ||||
| 	case consts.DataTypeInt: // Int类型 | ||||
| 		fallthrough | ||||
| 	case consts.DataTypeIntPtr: // Uint类型 | ||||
| 		val, err := gjson_hack.Int(sourceValue) | ||||
| 		return val, err | ||||
| 	case consts.DataTypeUint: | ||||
| 		fallthrough | ||||
| 	case consts.DataTypeUintPtr: // Uint类型 | ||||
| 		val, err := gjson_hack.Uint(sourceValue) | ||||
| 		return val, err | ||||
| 	case consts.DataTypeFloat: | ||||
| 		fallthrough | ||||
| 	case consts.DataTypeFloatPtr: // Float类型 | ||||
| 		val, err := gjson_hack.Float64(sourceValue) | ||||
| 		return val, err | ||||
| 	case consts.DataTypeString: // String类型 | ||||
| 		return sourceValue.String(), nil | ||||
| 	case consts.DataTypeBool: // Bool类型 | ||||
| 		return sourceValue.Bool(), nil | ||||
| 	case consts.DataTypeSliceFloat: // Float slice | ||||
| 		val, err := gjson_hack.SliceFloat(sourceValue) | ||||
| 		return val, err | ||||
| 	case consts.DataTypeSliceInt: // Int slice | ||||
| 		val, err := gjson_hack.SliceInt(sourceValue) | ||||
| 		return val, err | ||||
| 	case consts.DataTypeSliceUint: // Uint slice | ||||
| 		val, err := gjson_hack.SliceUint(sourceValue) | ||||
| 		return val, err | ||||
| 	case consts.DataTypeSliceString: // String slice | ||||
| 		val, err := gjson_hack.SliceString(sourceValue) | ||||
| 		return val, err | ||||
| 	case consts.DataTypeSliceBool: // Bool slice | ||||
| 		val, err := gjson_hack.SliceBool(sourceValue) | ||||
| 		return val, err | ||||
| 	case consts.DataTypeMapStrAny: // Bool slice | ||||
| 		val, err := gjson_hack.MapStrAny[any](sourceValue) | ||||
| 		return val, err | ||||
| 	} | ||||
| 	return sourceValue.Value(), nil | ||||
| } | ||||
|  | ||||
| // 生成结构体的tag标签 | ||||
| func (h *handle) generateTag(field StructField) string { | ||||
| 	tagList := []string{ | ||||
| 		fmt.Sprintf(`json:"%s"`, field.JsonTag), // json tag | ||||
| 	} | ||||
| 	if len(field.Errmsg) == 0 { | ||||
| 		field.Errmsg = field.JsonTag + ": 参数校验不通过" | ||||
| 	} | ||||
| 	tagList = append(tagList, fmt.Sprintf(`%s:"%s"`, TagErrMsg, field.Errmsg)) // 错误信息tag | ||||
| 	validateRuleList := []string{} | ||||
| 	for _, itemRule := range field.RuleList { | ||||
| 		if len(itemRule.Args) == 0 { | ||||
| 			validateRuleList = append(validateRuleList, itemRule.Tag) | ||||
| 		} else { | ||||
| 			validateRuleList = append(validateRuleList, fmt.Sprintf("%s=%s", itemRule.Tag, strings.Join(itemRule.Args, " "))) | ||||
| 		} | ||||
| 	} | ||||
| 	// 验证规则tag | ||||
| 	tagList = append(tagList, fmt.Sprintf(`%s:"%s"`, TagValidate, strings.Join(validateRuleList, ","))) | ||||
| 	// 默认值 | ||||
| 	tagList = append(tagList, fmt.Sprintf(`%s:"%s"`, TagDefaultValue, field.DefaultValue)) | ||||
| 	return strings.Join(tagList, " ") | ||||
| } | ||||
		Reference in New Issue
	
	Block a user