...

Source file src/github.com/go-playground/validator/v10/errors.go

Documentation: github.com/go-playground/validator/v10

     1  package validator
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"reflect"
     7  	"strings"
     8  
     9  	ut "github.com/go-playground/universal-translator"
    10  )
    11  
    12  const (
    13  	fieldErrMsg = "Key: '%s' Error:Field validation for '%s' failed on the '%s' tag"
    14  )
    15  
    16  // ValidationErrorsTranslations is the translation return type
    17  type ValidationErrorsTranslations map[string]string
    18  
    19  // InvalidValidationError describes an invalid argument passed to
    20  // `Struct`, `StructExcept`, StructPartial` or `Field`
    21  type InvalidValidationError struct {
    22  	Type reflect.Type
    23  }
    24  
    25  // Error returns InvalidValidationError message
    26  func (e *InvalidValidationError) Error() string {
    27  
    28  	if e.Type == nil {
    29  		return "validator: (nil)"
    30  	}
    31  
    32  	return "validator: (nil " + e.Type.String() + ")"
    33  }
    34  
    35  // ValidationErrors is an array of FieldError's
    36  // for use in custom error messages post validation.
    37  type ValidationErrors []FieldError
    38  
    39  // Error is intended for use in development + debugging and not intended to be a production error message.
    40  // It allows ValidationErrors to subscribe to the Error interface.
    41  // All information to create an error message specific to your application is contained within
    42  // the FieldError found within the ValidationErrors array
    43  func (ve ValidationErrors) Error() string {
    44  
    45  	buff := bytes.NewBufferString("")
    46  
    47  	for i := 0; i < len(ve); i++ {
    48  
    49  		buff.WriteString(ve[i].Error())
    50  		buff.WriteString("\n")
    51  	}
    52  
    53  	return strings.TrimSpace(buff.String())
    54  }
    55  
    56  // Translate translates all of the ValidationErrors
    57  func (ve ValidationErrors) Translate(ut ut.Translator) ValidationErrorsTranslations {
    58  
    59  	trans := make(ValidationErrorsTranslations)
    60  
    61  	var fe *fieldError
    62  
    63  	for i := 0; i < len(ve); i++ {
    64  		fe = ve[i].(*fieldError)
    65  
    66  		// // in case an Anonymous struct was used, ensure that the key
    67  		// // would be 'Username' instead of ".Username"
    68  		// if len(fe.ns) > 0 && fe.ns[:1] == "." {
    69  		// 	trans[fe.ns[1:]] = fe.Translate(ut)
    70  		// 	continue
    71  		// }
    72  
    73  		trans[fe.ns] = fe.Translate(ut)
    74  	}
    75  
    76  	return trans
    77  }
    78  
    79  // FieldError contains all functions to get error details
    80  type FieldError interface {
    81  
    82  	// Tag returns the validation tag that failed. if the
    83  	// validation was an alias, this will return the
    84  	// alias name and not the underlying tag that failed.
    85  	//
    86  	// eg. alias "iscolor": "hexcolor|rgb|rgba|hsl|hsla"
    87  	// will return "iscolor"
    88  	Tag() string
    89  
    90  	// ActualTag returns the validation tag that failed, even if an
    91  	// alias the actual tag within the alias will be returned.
    92  	// If an 'or' validation fails the entire or will be returned.
    93  	//
    94  	// eg. alias "iscolor": "hexcolor|rgb|rgba|hsl|hsla"
    95  	// will return "hexcolor|rgb|rgba|hsl|hsla"
    96  	ActualTag() string
    97  
    98  	// Namespace returns the namespace for the field error, with the tag
    99  	// name taking precedence over the field's actual name.
   100  	//
   101  	// eg. JSON name "User.fname"
   102  	//
   103  	// See StructNamespace() for a version that returns actual names.
   104  	//
   105  	// NOTE: this field can be blank when validating a single primitive field
   106  	// using validate.Field(...) as there is no way to extract it's name
   107  	Namespace() string
   108  
   109  	// StructNamespace returns the namespace for the field error, with the field's
   110  	// actual name.
   111  	//
   112  	// eq. "User.FirstName" see Namespace for comparison
   113  	//
   114  	// NOTE: this field can be blank when validating a single primitive field
   115  	// using validate.Field(...) as there is no way to extract its name
   116  	StructNamespace() string
   117  
   118  	// Field returns the fields name with the tag name taking precedence over the
   119  	// field's actual name.
   120  	//
   121  	// eq. JSON name "fname"
   122  	// see StructField for comparison
   123  	Field() string
   124  
   125  	// StructField returns the field's actual name from the struct, when able to determine.
   126  	//
   127  	// eq.  "FirstName"
   128  	// see Field for comparison
   129  	StructField() string
   130  
   131  	// Value returns the actual field's value in case needed for creating the error
   132  	// message
   133  	Value() interface{}
   134  
   135  	// Param returns the param value, in string form for comparison; this will also
   136  	// help with generating an error message
   137  	Param() string
   138  
   139  	// Kind returns the Field's reflect Kind
   140  	//
   141  	// eg. time.Time's kind is a struct
   142  	Kind() reflect.Kind
   143  
   144  	// Type returns the Field's reflect Type
   145  	//
   146  	// eg. time.Time's type is time.Time
   147  	Type() reflect.Type
   148  
   149  	// Translate returns the FieldError's translated error
   150  	// from the provided 'ut.Translator' and registered 'TranslationFunc'
   151  	//
   152  	// NOTE: if no registered translator can be found it returns the same as
   153  	// calling fe.Error()
   154  	Translate(ut ut.Translator) string
   155  
   156  	// Error returns the FieldError's message
   157  	Error() string
   158  }
   159  
   160  // compile time interface checks
   161  var _ FieldError = new(fieldError)
   162  var _ error = new(fieldError)
   163  
   164  // fieldError contains a single field's validation error along
   165  // with other properties that may be needed for error message creation
   166  // it complies with the FieldError interface
   167  type fieldError struct {
   168  	v              *Validate
   169  	tag            string
   170  	actualTag      string
   171  	ns             string
   172  	structNs       string
   173  	fieldLen       uint8
   174  	structfieldLen uint8
   175  	value          interface{}
   176  	param          string
   177  	kind           reflect.Kind
   178  	typ            reflect.Type
   179  }
   180  
   181  // Tag returns the validation tag that failed.
   182  func (fe *fieldError) Tag() string {
   183  	return fe.tag
   184  }
   185  
   186  // ActualTag returns the validation tag that failed, even if an
   187  // alias the actual tag within the alias will be returned.
   188  func (fe *fieldError) ActualTag() string {
   189  	return fe.actualTag
   190  }
   191  
   192  // Namespace returns the namespace for the field error, with the tag
   193  // name taking precedence over the field's actual name.
   194  func (fe *fieldError) Namespace() string {
   195  	return fe.ns
   196  }
   197  
   198  // StructNamespace returns the namespace for the field error, with the field's
   199  // actual name.
   200  func (fe *fieldError) StructNamespace() string {
   201  	return fe.structNs
   202  }
   203  
   204  // Field returns the field's name with the tag name taking precedence over the
   205  // field's actual name.
   206  func (fe *fieldError) Field() string {
   207  
   208  	return fe.ns[len(fe.ns)-int(fe.fieldLen):]
   209  	// // return fe.field
   210  	// fld := fe.ns[len(fe.ns)-int(fe.fieldLen):]
   211  
   212  	// log.Println("FLD:", fld)
   213  
   214  	// if len(fld) > 0 && fld[:1] == "." {
   215  	// 	return fld[1:]
   216  	// }
   217  
   218  	// return fld
   219  }
   220  
   221  // StructField returns the field's actual name from the struct, when able to determine.
   222  func (fe *fieldError) StructField() string {
   223  	// return fe.structField
   224  	return fe.structNs[len(fe.structNs)-int(fe.structfieldLen):]
   225  }
   226  
   227  // Value returns the actual field's value in case needed for creating the error
   228  // message
   229  func (fe *fieldError) Value() interface{} {
   230  	return fe.value
   231  }
   232  
   233  // Param returns the param value, in string form for comparison; this will
   234  // also help with generating an error message
   235  func (fe *fieldError) Param() string {
   236  	return fe.param
   237  }
   238  
   239  // Kind returns the Field's reflect Kind
   240  func (fe *fieldError) Kind() reflect.Kind {
   241  	return fe.kind
   242  }
   243  
   244  // Type returns the Field's reflect Type
   245  func (fe *fieldError) Type() reflect.Type {
   246  	return fe.typ
   247  }
   248  
   249  // Error returns the fieldError's error message
   250  func (fe *fieldError) Error() string {
   251  	return fmt.Sprintf(fieldErrMsg, fe.ns, fe.Field(), fe.tag)
   252  }
   253  
   254  // Translate returns the FieldError's translated error
   255  // from the provided 'ut.Translator' and registered 'TranslationFunc'
   256  //
   257  // NOTE: if no registered translation can be found, it returns the original
   258  // untranslated error message.
   259  func (fe *fieldError) Translate(ut ut.Translator) string {
   260  	var fn TranslationFunc
   261  
   262  	m, ok := fe.v.transTagFunc[ut]
   263  	if !ok {
   264  		return fe.Error()
   265  	}
   266  
   267  	fn, ok = m[fe.tag]
   268  	if !ok {
   269  		fn, ok = m[fe.actualTag]
   270  		if !ok {
   271  			return fe.Error()
   272  		}
   273  	}
   274  
   275  	return fn(ut, fe)
   276  }
   277  

View as plain text