|
|
|
@ -20,21 +20,22 @@ import ( |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
const ( |
|
|
|
|
utf8HexComma = "0x2C" |
|
|
|
|
utf8Pipe = "0x7C" |
|
|
|
|
tagSeparator = "," |
|
|
|
|
orSeparator = "|" |
|
|
|
|
tagKeySeparator = "=" |
|
|
|
|
structOnlyTag = "structonly" |
|
|
|
|
omitempty = "omitempty" |
|
|
|
|
skipValidationTag = "-" |
|
|
|
|
diveTag = "dive" |
|
|
|
|
existsTag = "exists" |
|
|
|
|
fieldErrMsg = "Key: \"%s\" Error:Field validation for \"%s\" failed on the \"%s\" tag" |
|
|
|
|
arrayIndexFieldName = "%s" + leftBracket + "%d" + rightBracket |
|
|
|
|
mapIndexFieldName = "%s" + leftBracket + "%v" + rightBracket |
|
|
|
|
invalidValidation = "Invalid validation tag on field %s" |
|
|
|
|
undefinedValidation = "Undefined validation function on field %s" |
|
|
|
|
utf8HexComma = "0x2C" |
|
|
|
|
utf8Pipe = "0x7C" |
|
|
|
|
tagSeparator = "," |
|
|
|
|
orSeparator = "|" |
|
|
|
|
tagKeySeparator = "=" |
|
|
|
|
structOnlyTag = "structonly" |
|
|
|
|
omitempty = "omitempty" |
|
|
|
|
skipValidationTag = "-" |
|
|
|
|
diveTag = "dive" |
|
|
|
|
existsTag = "exists" |
|
|
|
|
fieldErrMsg = "Key: \"%s\" Error:Field validation for \"%s\" failed on the \"%s\" tag" |
|
|
|
|
arrayIndexFieldName = "%s" + leftBracket + "%d" + rightBracket |
|
|
|
|
mapIndexFieldName = "%s" + leftBracket + "%v" + rightBracket |
|
|
|
|
invalidValidation = "Invalid validation tag on field %s" |
|
|
|
|
undefinedValidation = "Undefined validation function on field %s" |
|
|
|
|
validatorNotInitialized = "Validator instance not initialized" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
@ -78,6 +79,12 @@ type Validate struct { |
|
|
|
|
config Config |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (v *Validate) initCheck() { |
|
|
|
|
if v == nil { |
|
|
|
|
panic(validatorNotInitialized) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Config contains the options that a Validator instance will use.
|
|
|
|
|
// It is passed to the New() function
|
|
|
|
|
type Config struct { |
|
|
|
@ -146,6 +153,7 @@ func New(config Config) *Validate { |
|
|
|
|
// NOTE: if the key already exists, the previous validation function will be replaced.
|
|
|
|
|
// NOTE: this method is not thread-safe
|
|
|
|
|
func (v *Validate) RegisterValidation(key string, f Func) error { |
|
|
|
|
v.initCheck() |
|
|
|
|
|
|
|
|
|
if len(key) == 0 { |
|
|
|
|
return errors.New("Function Key cannot be empty") |
|
|
|
@ -162,6 +170,7 @@ func (v *Validate) RegisterValidation(key string, f Func) error { |
|
|
|
|
|
|
|
|
|
// RegisterCustomTypeFunc registers a CustomTypeFunc against a number of types
|
|
|
|
|
func (v *Validate) RegisterCustomTypeFunc(fn CustomTypeFunc, types ...interface{}) { |
|
|
|
|
v.initCheck() |
|
|
|
|
|
|
|
|
|
if v.config.CustomTypeFuncs == nil { |
|
|
|
|
v.config.CustomTypeFuncs = map[reflect.Type]CustomTypeFunc{} |
|
|
|
@ -178,6 +187,7 @@ func (v *Validate) RegisterCustomTypeFunc(fn CustomTypeFunc, types ...interface{ |
|
|
|
|
// NOTE: it returns ValidationErrors instead of a single FieldError because this can also
|
|
|
|
|
// validate Array, Slice and maps fields which may contain more than one error
|
|
|
|
|
func (v *Validate) Field(field interface{}, tag string) ValidationErrors { |
|
|
|
|
v.initCheck() |
|
|
|
|
|
|
|
|
|
errs := errsPool.Get().(ValidationErrors) |
|
|
|
|
fieldVal := reflect.ValueOf(field) |
|
|
|
@ -196,6 +206,7 @@ func (v *Validate) Field(field interface{}, tag string) ValidationErrors { |
|
|
|
|
// NOTE: it returns ValidationErrors instead of a single FieldError because this can also
|
|
|
|
|
// validate Array, Slice and maps fields which may contain more than one error
|
|
|
|
|
func (v *Validate) FieldWithValue(val interface{}, field interface{}, tag string) ValidationErrors { |
|
|
|
|
v.initCheck() |
|
|
|
|
|
|
|
|
|
errs := errsPool.Get().(ValidationErrors) |
|
|
|
|
topVal := reflect.ValueOf(val) |
|
|
|
@ -216,6 +227,7 @@ func (v *Validate) FieldWithValue(val interface{}, field interface{}, tag string |
|
|
|
|
// NOTE: This is normally not needed, however in some specific cases such as: tied to a
|
|
|
|
|
// legacy data structure, it will be useful
|
|
|
|
|
func (v *Validate) StructPartial(current interface{}, fields ...string) ValidationErrors { |
|
|
|
|
v.initCheck() |
|
|
|
|
|
|
|
|
|
sv, _ := v.extractType(reflect.ValueOf(current)) |
|
|
|
|
name := sv.Type().Name() |
|
|
|
@ -274,6 +286,7 @@ func (v *Validate) StructPartial(current interface{}, fields ...string) Validati |
|
|
|
|
// NOTE: This is normally not needed, however in some specific cases such as: tied to a
|
|
|
|
|
// legacy data structure, it will be useful
|
|
|
|
|
func (v *Validate) StructExcept(current interface{}, fields ...string) ValidationErrors { |
|
|
|
|
v.initCheck() |
|
|
|
|
|
|
|
|
|
sv, _ := v.extractType(reflect.ValueOf(current)) |
|
|
|
|
name := sv.Type().Name() |
|
|
|
@ -297,6 +310,7 @@ func (v *Validate) StructExcept(current interface{}, fields ...string) Validatio |
|
|
|
|
|
|
|
|
|
// Struct validates a structs exposed fields, and automatically validates nested structs, unless otherwise specified.
|
|
|
|
|
func (v *Validate) Struct(current interface{}) ValidationErrors { |
|
|
|
|
v.initCheck() |
|
|
|
|
|
|
|
|
|
errs := errsPool.Get().(ValidationErrors) |
|
|
|
|
sv := reflect.ValueOf(current) |
|
|
|
|