2

我有一个像这样的验证器结构

type UploadFileFormValidator struct {
    File       []*multipart.FileHeader `form:"File" binding:"required,min=1"`
    InputKey   string                  `form:"Key" binding:"disallowed-char"`
    Permission string                  `form:"Permission" binding:"disallowed-permission"`
}

并像下面一样使用它

func Bind(c *gin.Context, obj interface{}) error {
    b := binding.Default(c.Request.Method, c.ContentType())
    return c.ShouldBindWith(obj, b)
}

并像这样格式化我的错误

func NewValidatorError(err error) CommonError {
    res := CommonError{}
    res.Errors = make(map[string]interface{})

    errs := err.(validator.ValidationErrors)

    for _, v := range errs {
        if v.Param() != "" {
            res.Errors[v.Field()] = fmt.Sprintf("{%v: %v}", v.Tag(), v.Param())
        } else {
            res.Errors[v.Field()] = fmt.Sprintf("{key: %v}", v.Tag())
        }
    }

    return res
}

但问题是当我上传文件InputKeyPermission字段时,我不会validator.ValidationErrors按预期获得。

就像杜松子酒将这种情况视为其他类型的错误一样。

如何执行参数类型检查并仍然使用原始代码结构?

4

1 回答 1

0

但问题是当我在 InputKey 或 Permission Field 中上传文件时,我不会得到我预期的 validator.ValidationErrors

在这种情况下,您不会收到validator错误消息。失败的是完全绑定。根本没有达到验证步骤。

您必须确保模型字段正确映射到请求(查询或发布表单,假设您使用form绑定),即 Gin 绑定可以结构字段设置为开头。然后将进行验证,并可能产生一个validator.ValidationErrors.

为了清楚起见,这就是实现的queryBinding样子:

func (queryBinding) Bind(req *http.Request, obj interface{}) error {
    values := req.URL.Query()
    if err := mapForm(obj, values); err != nil {
        return err // you get stuck here
    }
    return validate(obj)
}

如您所见,模型映射发生在验证之前。

不幸的是,映射错误是不确定的,所以你不能很好地利用errors.As它来捕捉它。您可以做的是在断言验证错误时使用 comma-ok,如果失败,您就知道这是一个绑定问题。

errs, ok := err.(validator.ValidationErrors)
if !ok {
    // binding error
}
于 2022-01-14T07:39:29.900 回答