|
|
@ -2,6 +2,7 @@ package validator |
|
|
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
import ( |
|
|
|
"errors" |
|
|
|
"errors" |
|
|
|
|
|
|
|
"fmt" |
|
|
|
"log" |
|
|
|
"log" |
|
|
|
"reflect" |
|
|
|
"reflect" |
|
|
|
"strings" |
|
|
|
"strings" |
|
|
@ -9,7 +10,9 @@ import ( |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
const ( |
|
|
|
const ( |
|
|
|
|
|
|
|
defaultTagName = "validate" |
|
|
|
omitempty string = "omitempty" |
|
|
|
omitempty string = "omitempty" |
|
|
|
|
|
|
|
validationErrMsg = "Field validation for \"%s\" failed on the \"%s\" tag\n" |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
// FieldValidationError contains a single fields validation error
|
|
|
|
// FieldValidationError contains a single fields validation error
|
|
|
@ -18,6 +21,12 @@ type FieldValidationError struct { |
|
|
|
ErrorTag string |
|
|
|
ErrorTag string |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// This is intended for use in development + debugging and not intended to be a production error message.
|
|
|
|
|
|
|
|
// it also allows FieldValidationError to be used as an Error interface
|
|
|
|
|
|
|
|
func (e FieldValidationError) Error() string { |
|
|
|
|
|
|
|
return fmt.Sprintf(validationErrMsg, e.Field, e.ErrorTag) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// StructValidationErrors is a struct of errors for struct fields ( Excluding fields of type struct )
|
|
|
|
// StructValidationErrors is a struct of errors for struct fields ( Excluding fields of type struct )
|
|
|
|
// NOTE: if a field within a struct is a struct it's errors will not be contained within the current
|
|
|
|
// NOTE: if a field within a struct is a struct it's errors will not be contained within the current
|
|
|
|
// StructValidationErrors but rather a new StructValidationErrors is created for each struct resulting in
|
|
|
|
// StructValidationErrors but rather a new StructValidationErrors is created for each struct resulting in
|
|
|
@ -27,6 +36,19 @@ type StructValidationErrors struct { |
|
|
|
Errors map[string]*FieldValidationError |
|
|
|
Errors map[string]*FieldValidationError |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// This is intended for use in development + debugging and not intended to be a production error message.
|
|
|
|
|
|
|
|
// it also allows StructValidationErrors to be used as an Error interface
|
|
|
|
|
|
|
|
func (e StructValidationErrors) Error() string { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
s := "" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for _, err := range e.Errors { |
|
|
|
|
|
|
|
s += fmt.Sprintf(validationErrMsg, err.Field, err.ErrorTag) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return s |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// ValidationFunc that accepts the value of a field and parameter for use in validation (parameter not always used or needed)
|
|
|
|
// ValidationFunc that accepts the value of a field and parameter for use in validation (parameter not always used or needed)
|
|
|
|
type ValidationFunc func(v interface{}, param string) bool |
|
|
|
type ValidationFunc func(v interface{}, param string) bool |
|
|
|
|
|
|
|
|
|
|
@ -43,7 +65,7 @@ type Validator struct { |
|
|
|
|
|
|
|
|
|
|
|
// var bakedInValidators = map[string]ValidationFunc{}
|
|
|
|
// var bakedInValidators = map[string]ValidationFunc{}
|
|
|
|
|
|
|
|
|
|
|
|
var internalValidator = NewValidator("validate", bakedInValidators) |
|
|
|
var internalValidator = NewValidator(defaultTagName, bakedInValidators) |
|
|
|
|
|
|
|
|
|
|
|
// NewValidator creates a new Validator instance
|
|
|
|
// NewValidator creates a new Validator instance
|
|
|
|
// NOTE: it is not necessary to create a new validator as the internal one will do in 99.9% of cases, but the option is there.
|
|
|
|
// NOTE: it is not necessary to create a new validator as the internal one will do in 99.9% of cases, but the option is there.
|
|
|
@ -237,6 +259,7 @@ func (v *Validator) validateFieldByNameAndTag(f interface{}, name string, tag st |
|
|
|
log.Fatalf("Invalid validation tag on field %s", name) |
|
|
|
log.Fatalf("Invalid validation tag on field %s", name) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// OK to continue because we checked it's existance before getting into this loop
|
|
|
|
if key == omitempty { |
|
|
|
if key == omitempty { |
|
|
|
continue |
|
|
|
continue |
|
|
|
} |
|
|
|
} |
|
|
|