go validator参数校验器自定义规则及提示(自定义异常返回提示语)

原文连接:https://segmentfault.com/a/1190000040445612
笔者针对参数为指针的情况做了一点小优化

这里我们用validator用来做参数校验,gin默认的github.com/go-playground/validator,可以直接使用

除此之外还有一些其他的工具也挺好用的,例如:

  • github.com/asaskevich/govalidator

这里笔者就使用gin默认的了

然后开始使用,我们可以用来校验结构体

type UserBasic struct {utils.ProcessErr(userParams, err)
    UserId        uint64 `gorm:"column:user_id" json:"userId"`
    UserNumber    string `gorm:"column:user_number" json:"userNumber"`
    Name          string `validate:"required" reg_error_info:"姓名不能为空"`
    Age           uint8  `validate:"lt=0|gt=150" reg_error_info:"年龄不合法"`
    PassWord      string `gorm:"column:password" json:"password"`
    PhoneNum      string `validate:"RegexPhone" reg_error_info:"手机号格式不正确"`
    Email         string `validate:"email" reg_error_info:"email为空或格式不正确"`
  ...其他省略
}

这时一般返回的错误是这样的

image-20230130225947389

当然这样不友好,我们希望能够返回自定义的提醒信息,我们封装一个方法即可

// ProcessErr go validator参数校验器自定义规则及提示
func ProcessErr(u interface{}, err error) string {
	if err == nil { //如果为nil 说明校验通过
		return ""
	}
	invalid, ok := err.(*validator.InvalidValidationError) //如果是输入参数无效,则直接返回输入参数错误
	if ok {
		return "输入参数错误:" + invalid.Error()
	}
	validationErrs := err.(validator.ValidationErrors) //断言是ValidationErrors
	for _, validationErr := range validationErrs {
		fieldName := validationErr.Field() //获取是哪个字段不符合格式
		typeOf := reflect.TypeOf(u)
		// 如果是指针,获取其属性
		if typeOf.Kind() == reflect.Ptr {
			typeOf = typeOf.Elem()
		}
		field, ok := typeOf.FieldByName(fieldName) //通过反射获取filed
		if ok {
			errorInfo := field.Tag.Get("reg_error_info") // 获取field对应的reg_error_info tag值
			return fieldName + ":" + errorInfo           // 返回错误
		} else {
			return "缺失reg_error_info"
		}
	}
	return ""
}

再调用我们的方法即可

// 参数校验
validate := validator.New()
// 自定义校验
validate.RegisterValidation("RegexPhone", utils.RegexPhone)
if err := validate.Struct(userParams); err != nil {
  // 返回我们tag中的提示语
  c.JSON(-1, response.Err.WithMsg(utils.ProcessErr(userParams, err)))
  return
}

现在就是我们想要的结果了

image-20230130230149986

<think>好的,我需要帮助用户将现有的generateRules方法调整成生成特定格式的表单校验规则。用户提供的示例中的rules对象包含多个字段,每个字段的规则数组中有不同的校验条件,比如required、type、min/max等。而用户当前的generateRules方法只能处理required、pattern和number类型的情况,还需要扩展其他校验类型。 首先,我需要分析用户提供的示例rules结构,看看有哪些校验规则是当前方法没有覆盖的。例如,示例中的name字段有min和max的校验,region和resource有required和trigger,date1和date2有type: 'date',type字段有type: 'array'等。而现有的generateRules方法处理了required、pattern和number类型,但缺少对min/max、date、array等类型的支持。 接下来,我需要确定如何扩展generateRules方法,使其能够生成这些额外的校验规则。可能需要添加条件判断来处理不同的item.type,比如当item.type是'date'时添加type: 'date'的规则,当是'select'或类似类型时设置trigger为'change'。同时,还需要处理min和max的情况,可能在item对象中添加min和max属性,然后在方法中检查这些属性是否存在,并生成对应的规则。 另外,用户示例中的type字段使用了type: 'array',而当前方法中只有对number类型的处理。因此,需要在方法中添加对array类型的支持。可能还需要考虑其他类型,比如date、string等,根据不同的类型添加对应的type校验规则。 还需要注意trigger的触发方式。在用户示例中,对于select类型的字段(如region、resource),trigger是'change',而输入框类型的是'blur'。当前的generateRules方法在处理required时,根据item.type是否为select来设置trigger,但其他规则如pattern的trigger固定为'blur'。可能需要让其他规则也能根据不同的类型设置不同的trigger,或者保持当前逻辑,只在required规则中动态设置trigger。 此外,用户示例中的name字段有min和max的校验,而当前方法没有处理这两个属性。因此,需要在generateRules方法中添加对min和max的判断,如果item中存在这些属性,则生成对应的规则。例如: if (item.min !== undefined) { rules.push({ min: item.min, message: `${item.label}长度不能小于${item.min}`, trigger: 'blur' }); } if (item.max !== undefined) { rules.push({ max: item.max, message: `${item.label}长度不能超过${item.max}`, trigger: 'blur' }); } 但用户示例中的min和max消息是固定格式的,可能需要根据item的配置调整消息内容,或者让item包含minMessage和maxMessage属性。 还需要考虑如何将item.type映射到不同的校验规则。例如,当item.type是'date'时,添加type: 'date'的规则;如果是'array',则添加type: 'array'的规则。这可能需要更多的条件判断,或者在item对象中有一个明确的type属性来指定校验类型。 最后,需要确保生成的规则数组的结构与用户示例中的一致,每个字段的规则数组包含所有适用的校验规则对象。同时,可能需要处理多个trigger的情况,比如一个字段同时有blur和change触发校验,但用户示例中的每个规则对象只有一个trigger,可能需要合并或分开处理。 总结下来,步骤可能包括: 1. 扩展generateRules方法,增加对min、max、date、array等类型的支持。 2. 根据item的类型设置不同的trigger,特别是对于select等需要change触发的情况。 3. 确保各个校验规则的消息能够正确生成,可能通过item的属性动态设置。 4. 测试生成的规则是否符合用户提供的示例结构,确保每个字段的规则数组正确。</think>可以通过以下方案将 `generateRules` 方法升级为支持多类型校验的动态规则生成器: --- ### 一、方法改造思路 ```javascript methods: { generateRules(item) { const rules = []; // 必填校验 if (item.required) { rules.push({ required: true, message: `${item.label}${item.requiredMessage || '不能为空'}`, trigger: this.getTriggerType(item) // 动态触发器 }) } // 类型校验(扩展支持更多类型) if (item.type) { rules.push({ type: this.mapFieldType(item.type), // 类型映射 message: item.typeMessage || `${item.label}类型不符合要求`, trigger: this.getTriggerType(item) }) } // 正则校验 if (item.pattern) { rules.push({ pattern: new RegExp(item.pattern), message: item.patternMessage || `${item.label}格式错误`, trigger: 'blur' }) } // 长度校验(新增) if (item.min || item.max) { rules.push({ min: item.min, max: item.max, message: this.getLengthMessage(item), // 动态长度提示 trigger: 'blur' }) } // 自定义校验(扩展点) if (item.customValidator) { rules.push({ validator: item.customValidator, trigger: 'blur' }) } return rules }, // 获取触发方式 getTriggerType(item) { return ['select', 'checkbox', 'date'].includes(item.type) ? 'change' : 'blur' }, // 类型映射表 mapFieldType(type) { const typeMap = { number: 'number', date: 'date', array: 'array', email: 'email', // 可继续扩展... } return typeMap[type] || 'string' }, // 生成长度提示 getLengthMessage(item) { if (item.min && item.max) { return `${item.label}长度需在${item.min}-${item.max}之间` } return item.min ? `${item.label}长度不能小于${item.min}` : `${item.label}长度不能超过${item.max}` } } ``` --- ### 二、数据结构适配 需要传入的 `item` 数据结构示例: ```javascript formItems: [ { field: 'name', label: '活动名称', type: 'string', required: true, min: 3, max: 5 }, { field: 'region', label: '活动区域', type: 'select', required: true }, { field: 'date1', label: '日期', type: 'date', required: true }, { field: 'type', label: '活动性质', type: 'array', required: true } ] ``` --- ### 三、规则生成调用 ```javascript computed: { rules() { const rules = {} this.formItems.forEach(item => { rules[item.field] = this.generateRules(item) }) return rules } } ``` --- ### 四、支持的特性清单 | 校验类型 | 对应配置项 | 示例值 | |------------|--------------------------|-------------------------| | 必填校验 | required: true | 自动生成提示语 | | 字段类型 | type: 'date/number/...' | 支持6种标准类型 | | 正则校验 | pattern: 正则表达式 | `/^1\d{10}$/` | | 长度限制 | min/max | min:3, max:20 | | 自定义校验 | customValidator: 函数 | 自主实现验证逻辑 | | 触发方式 | 根据控件类型自动判断 | select→change | --- ### 五、扩展建议 1. **异步校验**:可在 `customValidator` 中实现接口验证 ```javascript customValidator: (rule, value, callback) => { axios.get('/check/username', { params: { value } }).then(res => { res.valid ? callback() : callback(new Error('名称已存在')) }) } ``` 2. **国际化**:将 `message` 生成逻辑提取为独立方法 ```javascript generateMessage(type, item) { const messages = { required: this.$t('validation.required', { label: item.label }), pattern: this.$t('validation.pattern', { label: item.label }) } return messages[type] } ``` --- ### 六、最终效果匹配 生成的规则对象将完全匹配目标格式: ```javascript rules: { name: [ { required: true, message: '活动名称不能为空', trigger: 'blur' }, { min: 3, max: 5, message: '活动名称长度需在3-5之间', trigger: 'blur' } ], region: [ { required: true, message: '活动区域不能为空', trigger: 'change' } ] // 其他字段同理... } ``` 通过这种设计,可以实现表单配置数据与验证规则的解耦,适合动态表单、低代码平台等场景。建议将 `formItems` 配置抽离为独立JSON文件,实现配置与逻辑分离。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值