gin_valid/go-playground/validator/v10/errors.go

296 lines
7.7 KiB
Go
Raw Normal View History

2020-12-05 15:21:52 +08:00
package validator
import (
"bytes"
"fmt"
"reflect"
"strings"
2020-12-05 15:37:56 +08:00
ut "git.ningdatech.com/ningda/gin_valid/go-playground/universal-translator"
2020-12-05 15:21:52 +08:00
)
const (
fieldErrMsg = "Key: '%s' Error:Field validation for '%s' failed on the '%s' tag"
)
// ValidationErrorsTranslations is the translation return type
type ValidationErrorsTranslations map[string]string
// InvalidValidationError describes an invalid argument passed to
// `Struct`, `StructExcept`, StructPartial` or `Field`
type InvalidValidationError struct {
Type reflect.Type
}
// Error returns InvalidValidationError message
func (e *InvalidValidationError) Error() string {
if e.Type == nil {
return "validator: (nil)"
}
return "validator: (nil " + e.Type.String() + ")"
}
// ValidationErrors is an array of FieldError's
// for use in custom error messages post validation.
type ValidationErrors []FieldError
// Error is intended for use in development + debugging and not intended to be a production error message.
// It allows ValidationErrors to subscribe to the Error interface.
// All information to create an error message specific to your application is contained within
// the FieldError found within the ValidationErrors array
func (ve ValidationErrors) Error() string {
buff := bytes.NewBufferString("")
var fe *fieldError
for i := 0; i < len(ve); i++ {
fe = ve[i].(*fieldError)
buff.WriteString(fe.Error())
buff.WriteString("\n")
}
return strings.TrimSpace(buff.String())
}
// yang 修改
// Translate translates all of the ValidationErrors
//func (ve ValidationErrors) Translate(ut ut.Translator) ValidationErrorsTranslations {
//
// trans := make(ValidationErrorsTranslations)
//
// var fe *fieldError
//
// for i := 0; i < len(ve); i++ {
// fe = ve[i].(*fieldError)
//
// // // in case an Anonymous struct was used, ensure that the key
// // // would be 'Username' instead of ".Username"
// // if len(fe.ns) > 0 && fe.ns[:1] == "." {
// // trans[fe.ns[1:]] = fe.Translate(ut)
// // continue
// // }
//
// trans[fe.ns] = fe.Translate(ut)
// }
//
// return trans
//}
type TransValidError struct {
ErrorString string
}
func (e TransValidError) Error() string {
return e.ErrorString
}
func (ve ValidationErrors) Translate(ut ut.Translator) TransValidError {
var result TransValidError
var fe *fieldError
if len(ve) == 0 {
return result
}
fe = ve[0].(*fieldError)
result.ErrorString = fe.Translate(ut)
return result
}
// yang 修改结束
// FieldError contains all functions to get error details
type FieldError interface {
// returns the validation tag that failed. if the
// validation was an alias, this will return the
// alias name and not the underlying tag that failed.
//
// eg. alias "iscolor": "hexcolor|rgb|rgba|hsl|hsla"
// will return "iscolor"
Tag() string
// returns the validation tag that failed, even if an
// alias the actual tag within the alias will be returned.
// If an 'or' validation fails the entire or will be returned.
//
// eg. alias "iscolor": "hexcolor|rgb|rgba|hsl|hsla"
// will return "hexcolor|rgb|rgba|hsl|hsla"
ActualTag() string
// returns the namespace for the field error, with the tag
// name taking precedence over the field's actual name.
//
// eg. JSON name "User.fname"
//
// See StructNamespace() for a version that returns actual names.
//
// NOTE: this field can be blank when validating a single primitive field
// using validate.Field(...) as there is no way to extract it's name
Namespace() string
// returns the namespace for the field error, with the field's
// actual name.
//
// eq. "User.FirstName" see Namespace for comparison
//
// NOTE: this field can be blank when validating a single primitive field
// using validate.Field(...) as there is no way to extract its name
StructNamespace() string
// returns the fields name with the tag name taking precedence over the
// field's actual name.
//
// eq. JSON name "fname"
// see StructField for comparison
Field() string
// returns the field's actual name from the struct, when able to determine.
//
// eq. "FirstName"
// see Field for comparison
StructField() string
// returns the actual field's value in case needed for creating the error
// message
Value() interface{}
// returns the param value, in string form for comparison; this will also
// help with generating an error message
Param() string
// Kind returns the Field's reflect Kind
//
// eg. time.Time's kind is a struct
Kind() reflect.Kind
// Type returns the Field's reflect Type
//
// // eg. time.Time's type is time.Time
Type() reflect.Type
// returns the FieldError's translated error
// from the provided 'ut.Translator' and registered 'TranslationFunc'
//
// NOTE: if no registered translator can be found it returns the same as
// calling fe.Error()
Translate(ut ut.Translator) string
// Error returns the FieldError's message
Error() string
}
// compile time interface checks
var _ FieldError = new(fieldError)
var _ error = new(fieldError)
// fieldError contains a single field's validation error along
// with other properties that may be needed for error message creation
// it complies with the FieldError interface
type fieldError struct {
v *Validate
tag string
actualTag string
ns string
structNs string
fieldLen uint8
structfieldLen uint8
value interface{}
param string
kind reflect.Kind
typ reflect.Type
}
// Tag returns the validation tag that failed.
func (fe *fieldError) Tag() string {
return fe.tag
}
// ActualTag returns the validation tag that failed, even if an
// alias the actual tag within the alias will be returned.
func (fe *fieldError) ActualTag() string {
return fe.actualTag
}
// Namespace returns the namespace for the field error, with the tag
// name taking precedence over the field's actual name.
func (fe *fieldError) Namespace() string {
return fe.ns
}
// StructNamespace returns the namespace for the field error, with the field's
// actual name.
func (fe *fieldError) StructNamespace() string {
return fe.structNs
}
// Field returns the field's name with the tag name taking precedence over the
// field's actual name.
func (fe *fieldError) Field() string {
return fe.ns[len(fe.ns)-int(fe.fieldLen):]
// // return fe.field
// fld := fe.ns[len(fe.ns)-int(fe.fieldLen):]
// log.Println("FLD:", fld)
// if len(fld) > 0 && fld[:1] == "." {
// return fld[1:]
// }
// return fld
}
// returns the field's actual name from the struct, when able to determine.
func (fe *fieldError) StructField() string {
// return fe.structField
return fe.structNs[len(fe.structNs)-int(fe.structfieldLen):]
}
// Value returns the actual field's value in case needed for creating the error
// message
func (fe *fieldError) Value() interface{} {
return fe.value
}
// Param returns the param value, in string form for comparison; this will
// also help with generating an error message
func (fe *fieldError) Param() string {
return fe.param
}
// Kind returns the Field's reflect Kind
func (fe *fieldError) Kind() reflect.Kind {
return fe.kind
}
// Type returns the Field's reflect Type
func (fe *fieldError) Type() reflect.Type {
return fe.typ
}
// Error returns the fieldError's error message
func (fe *fieldError) Error() string {
return fmt.Sprintf(fieldErrMsg, fe.ns, fe.Field(), fe.tag)
}
// Translate returns the FieldError's translated error
// from the provided 'ut.Translator' and registered 'TranslationFunc'
//
// NOTE: if no registered translation can be found, it returns the original
// untranslated error message.
func (fe *fieldError) Translate(ut ut.Translator) string {
m, ok := fe.v.transTagFunc[ut]
if !ok {
return fe.Error()
}
fn, ok := m[fe.tag]
if !ok {
return fe.Error()
}
return fn(ut, fe)
}