@@ -27,6 +27,9 @@ const (
2727type FieldValidationError struct {
2828 Field string
2929 ErrorTag string
30+ Kind reflect.Kind
31+ Param string
32+ Value interface {}
3033}
3134
3235// This is intended for use in development + debugging and not intended to be a production error message.
@@ -220,7 +223,7 @@ func (v *Validator) ValidateStruct(s interface{}) *StructValidationErrors {
220223
221224 default :
222225
223- if fieldError := v .validateStructFieldByTag (valueField .Interface (), typeField .Name , tag ); fieldError != nil {
226+ if fieldError := v .validateFieldByNameAndTag (valueField .Interface (), typeField .Name , tag ); fieldError != nil {
224227 validationErrors .Errors [fieldError .Field ] = fieldError
225228 // free up memory reference
226229 fieldError = nil
@@ -235,32 +238,19 @@ func (v *Validator) ValidateStruct(s interface{}) *StructValidationErrors {
235238 return validationErrors
236239}
237240
238- // ValidateFieldWithTag validates the given field by the given tag arguments
239- func (v * Validator ) validateStructFieldByTag (f interface {}, name string , tag string ) * FieldValidationError {
240-
241- if err := v .validateFieldByNameAndTag (f , name , tag ); err != nil {
242- return & FieldValidationError {
243- Field : name ,
244- ErrorTag : err .Error (),
245- }
246- }
247-
248- return nil
249- }
250-
251241// ValidateFieldByTag allows validation of a single field with the internal validator, still using tag style validation to check multiple errors
252- func ValidateFieldByTag (f interface {}, tag string ) error {
242+ func ValidateFieldByTag (f interface {}, tag string ) * FieldValidationError {
253243
254244 return internalValidator .validateFieldByNameAndTag (f , "" , tag )
255245}
256246
257247// ValidateFieldByTag allows validation of a single field, still using tag style validation to check multiple errors
258- func (v * Validator ) ValidateFieldByTag (f interface {}, tag string ) error {
248+ func (v * Validator ) ValidateFieldByTag (f interface {}, tag string ) * FieldValidationError {
259249
260250 return v .validateFieldByNameAndTag (f , "" , tag )
261251}
262252
263- func (v * Validator ) validateFieldByNameAndTag (f interface {}, name string , tag string ) error {
253+ func (v * Validator ) validateFieldByNameAndTag (f interface {}, name string , tag string ) * FieldValidationError {
264254
265255 // This is a double check if coming from ValidateStruct but need to be here in case function is called directly
266256 if tag == "-" {
@@ -283,7 +273,8 @@ func (v *Validator) validateFieldByNameAndTag(f interface{}, name string, tag st
283273 panic ("Invalid field passed to ValidateFieldWithTag" )
284274 }
285275
286- // TODO: validate commas in regex's
276+ var valErr * FieldValidationError
277+ var err error
287278 valTags := strings .Split (tag , "," )
288279
289280 for _ , valTag := range valTags {
@@ -296,62 +287,35 @@ func (v *Validator) validateFieldByNameAndTag(f interface{}, name string, tag st
296287
297288 for _ , val := range orVals {
298289
299- key , err : = v .validateFieldByNameAndSingleTag (f , name , val )
290+ valErr , err = v .validateFieldByNameAndSingleTag (f , name , val )
300291
301292 if err == nil {
302293 return nil
303294 }
304295
305- errTag += "|" + key
296+ errTag += "|" + valErr . ErrorTag
306297
307298 }
308299
309300 errTag = strings .TrimLeft (errTag , "|" )
310301
311- return errors . New ( errTag )
312- }
302+ valErr . ErrorTag = errTag
303+ valErr . Kind = valueField . Kind ()
313304
314- if _ , err := v .validateFieldByNameAndSingleTag (f , name , valTag ); err != nil {
315- return err
305+ return valErr
316306 }
317307
318- // TODO: validate = in regex's
319- // vals := strings.Split(valTag, "=")
320- // key := strings.Trim(vals[0], " ")
321- //
322- // if len(key) == 0 {
323- // panic(fmt.Sprintf("Invalid validation tag on field %s", name))
324- // }
325- //
326- // // OK to continue because we checked it's existance before getting into this loop
327- // if key == omitempty {
328- // continue
329- // }
330- //
331- // valFunc, ok := v.validationFuncs[key]
332- // if !ok {
333- // panic(fmt.Sprintf("Undefined validation function on field %s", name))
334- // }
335- //
336- // param := ""
337- // if len(vals) > 1 {
338- // param = strings.Trim(vals[1], " ")
339- // }
340- //
341- // if err := valFunc(f, param); !err {
342- //
343- // return errors.New(key)
344- // }
345- // if err := v.validateFieldByNameAndSingleTag(f, name, valTag); err != nil {
346- // return err
347- // }
308+ if valErr , err = v .validateFieldByNameAndSingleTag (f , name , valTag ); err != nil {
309+ valErr .Kind = valueField .Kind ()
348310
311+ return valErr
312+ }
349313 }
350314
351315 return nil
352316}
353317
354- func (v * Validator ) validateFieldByNameAndSingleTag (f interface {}, name string , valTag string ) (string , error ) {
318+ func (v * Validator ) validateFieldByNameAndSingleTag (f interface {}, name string , valTag string ) (* FieldValidationError , error ) {
355319
356320 vals := strings .Split (valTag , "=" )
357321 key := strings .Trim (vals [0 ], " " )
@@ -360,9 +324,16 @@ func (v *Validator) validateFieldByNameAndSingleTag(f interface{}, name string,
360324 panic (fmt .Sprintf ("Invalid validation tag on field %s" , name ))
361325 }
362326
327+ valErr := & FieldValidationError {
328+ Field : name ,
329+ ErrorTag : key ,
330+ Value : f ,
331+ Param : "" ,
332+ }
333+
363334 // OK to continue because we checked it's existance before getting into this loop
364335 if key == omitempty {
365- return key , nil
336+ return valErr , nil
366337 }
367338
368339 valFunc , ok := v .validationFuncs [key ]
@@ -376,8 +347,9 @@ func (v *Validator) validateFieldByNameAndSingleTag(f interface{}, name string,
376347 }
377348
378349 if err := valFunc (f , param ); ! err {
379- return key , errors .New (key )
350+ valErr .Param = param
351+ return valErr , errors .New (key )
380352 }
381353
382- return key , nil
354+ return valErr , nil
383355}
0 commit comments