package validation import ( "errors" "fmt" "reflect" "strings" "github.com/go-playground/validator/v10" ) var customMessages = map[string]string{ "required": "Field %s is required", "required_strict": "Field %s is required and cannot be null or empty", "omitempty_strict": "Field %s cannot be null or empty when provided", "email": "Invalid email address for field %s", "min": "Field %s must have a minimum length of %s characters", "max": "Field %s must have a maximum length of %s characters", "len": "Field %s must be exactly %s characters long", "number": "Field %s must be a number", "positive": "Field %s must be a positive number", "alphanum": "Field %s must contain only alphanumeric characters", "oneof": "Invalid value for field %s", "password": "Field %s must be at least 8 characters, contain uppercase, lowercase, number, and special character", "gt": "Invalid %s, must be greater than %s", } func CustomErrorMessages(err error) (string, map[string]string) { var validationErrors validator.ValidationErrors if errors.As(err, &validationErrors) { return generateErrorMessages(validationErrors) } return "", nil } func generateErrorMessages(validationErrors validator.ValidationErrors) (string, map[string]string) { errorsMap := make(map[string]string) var firstMessage string for i, err := range validationErrors { fieldName := err.StructNamespace() tag := err.Tag() customMessage := customMessages[tag] var msg string if customMessage != "" { msg = formatErrorMessage(customMessage, err, tag) } else { msg = defaultErrorMessage(err) } errorsMap[fieldName] = msg if i == 0 { firstMessage = msg } } return firstMessage, errorsMap } func formatErrorMessage(customMessage string, err validator.FieldError, tag string) string { if tag == "min" || tag == "max" || tag == "len" || tag == "gt" { return fmt.Sprintf(customMessage, err.Field(), err.Param()) } return fmt.Sprintf(customMessage, err.Field()) } func defaultErrorMessage(err validator.FieldError) string { return fmt.Sprintf("Field validation for '%s' failed on the '%s' tag", err.Field(), err.Tag()) } func Validator() *validator.Validate { validate := validator.New() validate.RegisterTagNameFunc(func(fld reflect.StructField) string { if jsonTag := getTagName(fld, "json"); jsonTag != "" { return jsonTag } if queryTag := getTagName(fld, "query"); queryTag != "" { return queryTag } return fld.Name }) if err := validate.RegisterValidation("password", Password); err != nil { return nil } if err := validate.RegisterValidation("required_strict", RequiredStrict); err != nil { return nil } if err := validate.RegisterValidation("omitempty_strict", OmitemptyStrict); err != nil { return nil } return validate } func getTagName(fld reflect.StructField, tag string) string { value, ok := fld.Tag.Lookup(tag) if !ok || value == "-" { return "" } name := strings.Split(value, ",")[0] if name == "" || name == "-" { return "" } return name }