go-playground / validator

:100:Go Struct and Field validation, including Cross Field, Cross Struct, Map, Slice and Array diving
MIT License
16.05k stars 1.29k forks source link

Multiple validations at one time #1268

Open reversersed opened 1 month ago

reversersed commented 1 month ago

Package version eg. v9, v10:

v10

Issue, Question or Enhancement:

I have several validation tags, but validator works sequently, so I get only one error per field at the time. Is there some way to validate all tags at one time?

Code sample, to showcase or reproduce:

type UserRegisterQuery struct {
    Login    string `json:"login" validate:"required,min=4,max=16" example:"user"`
    Email    string `json:"email" validate:"required,email" example:"user@example.com"`
    Password string `json:"password" validate:"required,min=8,max=32,lowercase,uppercase,digitrequired,specialsymbol" example:"User!1password"`
}

func ValidationError(errors validator.ValidationErrors, dev_message string) *Error {
    var errs []string
    for _, err := range errors {
        switch err.Tag() {
        case "required":
            errs = append(errs, fmt.Sprintf("%s: field is required", err.Field()))
        case "oneof":
            errs = append(errs, fmt.Sprintf("%s: field can only be: %s", err.Field(), err.ActualTag()))
        case "min":
            errs = append(errs, fmt.Sprintf("%s must be at least %s characters length", err.Field(), err.ActualTag()))
        case "max":
            errs = append(errs, fmt.Sprintf("%s can't be more that %s characters length", err.Field(), err.ActualTag()))
        case "email":
            errs = append(errs, fmt.Sprintf("%s must be a valid email", err.Field()))
        case "jwt":
            errs = append(errs, fmt.Sprintf("%s must be a JWT token", err.Field()))
        case "lowercase":
            errs = append(errs, fmt.Sprintf("%s must contain at least one lowercase character", err.Field()))
        case "uppercase":
            errs = append(errs, fmt.Sprintf("%s must contain at least one uppercase character", err.Field()))
        case "digitrequired":
            errs = append(errs, fmt.Sprintf("%s must contain at least one digit", err.Field()))
        case "specialsymbol":
            errs = append(errs, fmt.Sprintf("%s must contain at least one special symbol", err.Field()))
        default:
            errs = append(errs, err.Error())
        }
    }
    return NewError(errs, "IE-0004", dev_message)
}

func Handler() error {
    ...
    if err := validator.Struct(query); err != nil {
        return mw.ValidationError(err.(validator.ValidationErrors), "wrong query format")
    }
    ...
}

Now I get:

{
  "messages": [
    "Password must contain at least one uppercase character"
  ]
}

But I want it to be:

{
  "messages": [
    "Password must contain at least one uppercase character",
    "Password must contain at least one lowercase character",
    "Password must contain at least one special symbol"
  ]
}