Merge branch 'v1' into v2-development

pull/16/head
Dean Karn 10 years ago
commit 6d279552df
  1. 4
      doc.go
  2. 88
      validator.go
  3. 92
      validator_test.go

@ -8,7 +8,7 @@ but you may also create a new instance if needed.
// built in // built in
errs := validator.ValidateStruct(//your struct) errs := validator.ValidateStruct(//your struct)
errs := validator.ValidateFieldByTag(field, "omitempty,min=1,max=10") valErr := validator.ValidateFieldByTag(field, "omitempty,min=1,max=10")
// new // new
newValidator = validator.New("struct tag name", validator.BakedInFunctions) newValidator = validator.New("struct tag name", validator.BakedInFunctions)
@ -57,7 +57,7 @@ intended use is for development + debugging, not a production error message.
Why not a better error message? because this library intends for you to handle your own error messages Why not a better error message? because this library intends for you to handle your own error messages
Why should I handle my own errors? Many reasons, for me building and internationalized application Why should I handle my own errors? Many reasons, for me building an internationalized application
I needed to know the field and what validation failed so that I could provide an error in the users specific language. I needed to know the field and what validation failed so that I could provide an error in the users specific language.
if fieldErr.Field == "Name" { if fieldErr.Field == "Name" {

@ -27,6 +27,9 @@ const (
type FieldValidationError struct { type FieldValidationError struct {
Field string Field string
ErrorTag string ErrorTag string
Kind reflect.Kind
Param string
Value interface{}
} }
// This is intended for use in development + debugging and not intended to be a production error message. // 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 {
default: default:
if fieldError := v.validateStructFieldByTag(valueField.Interface(), typeField.Name, tag); fieldError != nil { if fieldError := v.validateFieldByNameAndTag(valueField.Interface(), typeField.Name, tag); fieldError != nil {
validationErrors.Errors[fieldError.Field] = fieldError validationErrors.Errors[fieldError.Field] = fieldError
// free up memory reference // free up memory reference
fieldError = nil fieldError = nil
@ -235,32 +238,19 @@ func (v *Validator) ValidateStruct(s interface{}) *StructValidationErrors {
return validationErrors return validationErrors
} }
// ValidateFieldWithTag validates the given field by the given tag arguments
func (v *Validator) validateStructFieldByTag(f interface{}, name string, tag string) *FieldValidationError {
if err := v.validateFieldByNameAndTag(f, name, tag); err != nil {
return &FieldValidationError{
Field: name,
ErrorTag: err.Error(),
}
}
return nil
}
// ValidateFieldByTag allows validation of a single field with the internal validator, still using tag style validation to check multiple errors // ValidateFieldByTag allows validation of a single field with the internal validator, still using tag style validation to check multiple errors
func ValidateFieldByTag(f interface{}, tag string) error { func ValidateFieldByTag(f interface{}, tag string) *FieldValidationError {
return internalValidator.validateFieldByNameAndTag(f, "", tag) return internalValidator.validateFieldByNameAndTag(f, "", tag)
} }
// ValidateFieldByTag allows validation of a single field, still using tag style validation to check multiple errors // ValidateFieldByTag allows validation of a single field, still using tag style validation to check multiple errors
func (v *Validator) ValidateFieldByTag(f interface{}, tag string) error { func (v *Validator) ValidateFieldByTag(f interface{}, tag string) *FieldValidationError {
return v.validateFieldByNameAndTag(f, "", tag) return v.validateFieldByNameAndTag(f, "", tag)
} }
func (v *Validator) validateFieldByNameAndTag(f interface{}, name string, tag string) error { func (v *Validator) validateFieldByNameAndTag(f interface{}, name string, tag string) *FieldValidationError {
// This is a double check if coming from ValidateStruct but need to be here in case function is called directly // This is a double check if coming from ValidateStruct but need to be here in case function is called directly
if tag == "-" { if tag == "-" {
@ -283,7 +273,8 @@ func (v *Validator) validateFieldByNameAndTag(f interface{}, name string, tag st
panic("Invalid field passed to ValidateFieldWithTag") panic("Invalid field passed to ValidateFieldWithTag")
} }
// TODO: validate commas in regex's var valErr *FieldValidationError
var err error
valTags := strings.Split(tag, ",") valTags := strings.Split(tag, ",")
for _, valTag := range valTags { for _, valTag := range valTags {
@ -296,62 +287,35 @@ func (v *Validator) validateFieldByNameAndTag(f interface{}, name string, tag st
for _, val := range orVals { for _, val := range orVals {
key, err := v.validateFieldByNameAndSingleTag(f, name, val) valErr, err = v.validateFieldByNameAndSingleTag(f, name, val)
if err == nil { if err == nil {
return nil return nil
} }
errTag += "|" + key errTag += "|" + valErr.ErrorTag
} }
errTag = strings.TrimLeft(errTag, "|") errTag = strings.TrimLeft(errTag, "|")
return errors.New(errTag) valErr.ErrorTag = errTag
} valErr.Kind = valueField.Kind()
if _, err := v.validateFieldByNameAndSingleTag(f, name, valTag); err != nil { return valErr
return err
} }
// TODO: validate = in regex's if valErr, err = v.validateFieldByNameAndSingleTag(f, name, valTag); err != nil {
// vals := strings.Split(valTag, "=") valErr.Kind = valueField.Kind()
// key := strings.Trim(vals[0], " ")
//
// if len(key) == 0 {
// panic(fmt.Sprintf("Invalid validation tag on field %s", name))
// }
//
// // OK to continue because we checked it's existance before getting into this loop
// if key == omitempty {
// continue
// }
//
// valFunc, ok := v.validationFuncs[key]
// if !ok {
// panic(fmt.Sprintf("Undefined validation function on field %s", name))
// }
//
// param := ""
// if len(vals) > 1 {
// param = strings.Trim(vals[1], " ")
// }
//
// if err := valFunc(f, param); !err {
//
// return errors.New(key)
// }
// if err := v.validateFieldByNameAndSingleTag(f, name, valTag); err != nil {
// return err
// }
return valErr
}
} }
return nil return nil
} }
func (v *Validator) validateFieldByNameAndSingleTag(f interface{}, name string, valTag string) (string, error) { func (v *Validator) validateFieldByNameAndSingleTag(f interface{}, name string, valTag string) (*FieldValidationError, error) {
vals := strings.Split(valTag, "=") vals := strings.Split(valTag, "=")
key := strings.Trim(vals[0], " ") key := strings.Trim(vals[0], " ")
@ -360,9 +324,16 @@ func (v *Validator) validateFieldByNameAndSingleTag(f interface{}, name string,
panic(fmt.Sprintf("Invalid validation tag on field %s", name)) panic(fmt.Sprintf("Invalid validation tag on field %s", name))
} }
valErr := &FieldValidationError{
Field: name,
ErrorTag: key,
Value: f,
Param: "",
}
// OK to continue because we checked it's existance before getting into this loop // OK to continue because we checked it's existance before getting into this loop
if key == omitempty { if key == omitempty {
return key, nil return valErr, nil
} }
valFunc, ok := v.validationFuncs[key] valFunc, ok := v.validationFuncs[key]
@ -376,8 +347,9 @@ func (v *Validator) validateFieldByNameAndSingleTag(f interface{}, name string,
} }
if err := valFunc(f, param); !err { if err := valFunc(f, param); !err {
return key, errors.New(key) valErr.Param = param
return valErr, errors.New(key)
} }
return key, nil return valErr, nil
} }

@ -169,7 +169,7 @@ func (ms *MySuite) TestUrl(c *C) {
c.Assert(err, IsNil) c.Assert(err, IsNil)
} else { } else {
c.Assert(err, NotNil) c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "url") c.Assert(err.ErrorTag, Equals, "url")
} }
} }
} }
@ -222,7 +222,7 @@ func (ms *MySuite) TestUri(c *C) {
c.Assert(err, IsNil) c.Assert(err, IsNil)
} else { } else {
c.Assert(err, NotNil) c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "uri") c.Assert(err.ErrorTag, Equals, "uri")
} }
} }
} }
@ -239,12 +239,12 @@ func (ms *MySuite) TestOrTag(c *C) {
s = "this ain't right" s = "this ain't right"
err = validator.ValidateFieldByTag(s, "rgb|rgba") err = validator.ValidateFieldByTag(s, "rgb|rgba")
c.Assert(err, NotNil) c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "rgb|rgba") c.Assert(err.ErrorTag, Equals, "rgb|rgba")
s = "this ain't right" s = "this ain't right"
err = validator.ValidateFieldByTag(s, "rgb|rgba|len=10") err = validator.ValidateFieldByTag(s, "rgb|rgba|len=10")
c.Assert(err, NotNil) c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "rgb|rgba|len") c.Assert(err.ErrorTag, Equals, "rgb|rgba|len")
s = "this is right" s = "this is right"
err = validator.ValidateFieldByTag(s, "rgb|rgba|len=13") err = validator.ValidateFieldByTag(s, "rgb|rgba|len=13")
@ -272,27 +272,27 @@ func (ms *MySuite) TestHsla(c *C) {
s = "hsl(361,100%,50%,1)" s = "hsl(361,100%,50%,1)"
err = validator.ValidateFieldByTag(s, "hsla") err = validator.ValidateFieldByTag(s, "hsla")
c.Assert(err, NotNil) c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "hsla") c.Assert(err.ErrorTag, Equals, "hsla")
s = "hsl(361,100%,50%)" s = "hsl(361,100%,50%)"
err = validator.ValidateFieldByTag(s, "hsla") err = validator.ValidateFieldByTag(s, "hsla")
c.Assert(err, NotNil) c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "hsla") c.Assert(err.ErrorTag, Equals, "hsla")
s = "hsla(361,100%,50%)" s = "hsla(361,100%,50%)"
err = validator.ValidateFieldByTag(s, "hsla") err = validator.ValidateFieldByTag(s, "hsla")
c.Assert(err, NotNil) c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "hsla") c.Assert(err.ErrorTag, Equals, "hsla")
s = "hsla(360,101%,50%)" s = "hsla(360,101%,50%)"
err = validator.ValidateFieldByTag(s, "hsla") err = validator.ValidateFieldByTag(s, "hsla")
c.Assert(err, NotNil) c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "hsla") c.Assert(err.ErrorTag, Equals, "hsla")
s = "hsla(360,100%,101%)" s = "hsla(360,100%,101%)"
err = validator.ValidateFieldByTag(s, "hsla") err = validator.ValidateFieldByTag(s, "hsla")
c.Assert(err, NotNil) c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "hsla") c.Assert(err.ErrorTag, Equals, "hsla")
} }
func (ms *MySuite) TestHsl(c *C) { func (ms *MySuite) TestHsl(c *C) {
@ -308,22 +308,22 @@ func (ms *MySuite) TestHsl(c *C) {
s = "hsl(361,100%,50%)" s = "hsl(361,100%,50%)"
err = validator.ValidateFieldByTag(s, "hsl") err = validator.ValidateFieldByTag(s, "hsl")
c.Assert(err, NotNil) c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "hsl") c.Assert(err.ErrorTag, Equals, "hsl")
s = "hsl(361,101%,50%)" s = "hsl(361,101%,50%)"
err = validator.ValidateFieldByTag(s, "hsl") err = validator.ValidateFieldByTag(s, "hsl")
c.Assert(err, NotNil) c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "hsl") c.Assert(err.ErrorTag, Equals, "hsl")
s = "hsl(361,100%,101%)" s = "hsl(361,100%,101%)"
err = validator.ValidateFieldByTag(s, "hsl") err = validator.ValidateFieldByTag(s, "hsl")
c.Assert(err, NotNil) c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "hsl") c.Assert(err.ErrorTag, Equals, "hsl")
s = "hsl(-10,100%,100%)" s = "hsl(-10,100%,100%)"
err = validator.ValidateFieldByTag(s, "hsl") err = validator.ValidateFieldByTag(s, "hsl")
c.Assert(err, NotNil) c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "hsl") c.Assert(err.ErrorTag, Equals, "hsl")
} }
func (ms *MySuite) TestRgba(c *C) { func (ms *MySuite) TestRgba(c *C) {
@ -343,17 +343,17 @@ func (ms *MySuite) TestRgba(c *C) {
s = "rgb(0, 31, 255)" s = "rgb(0, 31, 255)"
err = validator.ValidateFieldByTag(s, "rgba") err = validator.ValidateFieldByTag(s, "rgba")
c.Assert(err, NotNil) c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "rgba") c.Assert(err.ErrorTag, Equals, "rgba")
s = "rgb(1,349,275,0.5)" s = "rgb(1,349,275,0.5)"
err = validator.ValidateFieldByTag(s, "rgba") err = validator.ValidateFieldByTag(s, "rgba")
c.Assert(err, NotNil) c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "rgba") c.Assert(err.ErrorTag, Equals, "rgba")
s = "rgb(01,31,255,0.5)" s = "rgb(01,31,255,0.5)"
err = validator.ValidateFieldByTag(s, "rgba") err = validator.ValidateFieldByTag(s, "rgba")
c.Assert(err, NotNil) c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "rgba") c.Assert(err.ErrorTag, Equals, "rgba")
} }
func (ms *MySuite) TestRgb(c *C) { func (ms *MySuite) TestRgb(c *C) {
@ -369,17 +369,17 @@ func (ms *MySuite) TestRgb(c *C) {
s = "rgb(1,349,275)" s = "rgb(1,349,275)"
err = validator.ValidateFieldByTag(s, "rgb") err = validator.ValidateFieldByTag(s, "rgb")
c.Assert(err, NotNil) c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "rgb") c.Assert(err.ErrorTag, Equals, "rgb")
s = "rgb(01,31,255)" s = "rgb(01,31,255)"
err = validator.ValidateFieldByTag(s, "rgb") err = validator.ValidateFieldByTag(s, "rgb")
c.Assert(err, NotNil) c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "rgb") c.Assert(err.ErrorTag, Equals, "rgb")
s = "rgba(0,31,255)" s = "rgba(0,31,255)"
err = validator.ValidateFieldByTag(s, "rgb") err = validator.ValidateFieldByTag(s, "rgb")
c.Assert(err, NotNil) c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "rgb") c.Assert(err.ErrorTag, Equals, "rgb")
} }
func (ms *MySuite) TestEmail(c *C) { func (ms *MySuite) TestEmail(c *C) {
@ -390,19 +390,23 @@ func (ms *MySuite) TestEmail(c *C) {
s = "" s = ""
err = validator.ValidateFieldByTag(s, "email") err = validator.ValidateFieldByTag(s, "email")
c.Assert(err.Error(), Equals, "email") c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "email")
s = "test@email" s = "test@email"
err = validator.ValidateFieldByTag(s, "email") err = validator.ValidateFieldByTag(s, "email")
c.Assert(err.Error(), Equals, "email") c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "email")
s = "test@email." s = "test@email."
err = validator.ValidateFieldByTag(s, "email") err = validator.ValidateFieldByTag(s, "email")
c.Assert(err.Error(), Equals, "email") c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "email")
s = "@email.com" s = "@email.com"
err = validator.ValidateFieldByTag(s, "email") err = validator.ValidateFieldByTag(s, "email")
c.Assert(err.Error(), Equals, "email") c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "email")
} }
func (ms *MySuite) TestHexColor(c *C) { func (ms *MySuite) TestHexColor(c *C) {
@ -417,11 +421,13 @@ func (ms *MySuite) TestHexColor(c *C) {
s = "fff" s = "fff"
err = validator.ValidateFieldByTag(s, "hexcolor") err = validator.ValidateFieldByTag(s, "hexcolor")
c.Assert(err.Error(), Equals, "hexcolor") c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "hexcolor")
s = "fffFF" s = "fffFF"
err = validator.ValidateFieldByTag(s, "hexcolor") err = validator.ValidateFieldByTag(s, "hexcolor")
c.Assert(err.Error(), Equals, "hexcolor") c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "hexcolor")
} }
func (ms *MySuite) TestHexadecimal(c *C) { func (ms *MySuite) TestHexadecimal(c *C) {
@ -432,7 +438,8 @@ func (ms *MySuite) TestHexadecimal(c *C) {
s = "abcdefg" s = "abcdefg"
err = validator.ValidateFieldByTag(s, "hexadecimal") err = validator.ValidateFieldByTag(s, "hexadecimal")
c.Assert(err.Error(), Equals, "hexadecimal") c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "hexadecimal")
} }
func (ms *MySuite) TestNumber(c *C) { func (ms *MySuite) TestNumber(c *C) {
@ -443,31 +450,38 @@ func (ms *MySuite) TestNumber(c *C) {
s = "+1" s = "+1"
err = validator.ValidateFieldByTag(s, "number") err = validator.ValidateFieldByTag(s, "number")
c.Assert(err.Error(), Equals, "number") c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "number")
s = "-1" s = "-1"
err = validator.ValidateFieldByTag(s, "number") err = validator.ValidateFieldByTag(s, "number")
c.Assert(err.Error(), Equals, "number") c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "number")
s = "1.12" s = "1.12"
err = validator.ValidateFieldByTag(s, "number") err = validator.ValidateFieldByTag(s, "number")
c.Assert(err.Error(), Equals, "number") c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "number")
s = "+1.12" s = "+1.12"
err = validator.ValidateFieldByTag(s, "number") err = validator.ValidateFieldByTag(s, "number")
c.Assert(err.Error(), Equals, "number") c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "number")
s = "-1.12" s = "-1.12"
err = validator.ValidateFieldByTag(s, "number") err = validator.ValidateFieldByTag(s, "number")
c.Assert(err.Error(), Equals, "number") c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "number")
s = "1." s = "1."
err = validator.ValidateFieldByTag(s, "number") err = validator.ValidateFieldByTag(s, "number")
c.Assert(err.Error(), Equals, "number") c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "number")
s = "1.o" s = "1.o"
err = validator.ValidateFieldByTag(s, "number") err = validator.ValidateFieldByTag(s, "number")
c.Assert(err.Error(), Equals, "number") c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "number")
} }
func (ms *MySuite) TestNumeric(c *C) { func (ms *MySuite) TestNumeric(c *C) {
@ -498,11 +512,13 @@ func (ms *MySuite) TestNumeric(c *C) {
s = "1." s = "1."
err = validator.ValidateFieldByTag(s, "numeric") err = validator.ValidateFieldByTag(s, "numeric")
c.Assert(err.Error(), Equals, "numeric") c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "numeric")
s = "1.o" s = "1.o"
err = validator.ValidateFieldByTag(s, "numeric") err = validator.ValidateFieldByTag(s, "numeric")
c.Assert(err.Error(), Equals, "numeric") c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "numeric")
} }
func (ms *MySuite) TestAlphaNumeric(c *C) { func (ms *MySuite) TestAlphaNumeric(c *C) {
@ -513,7 +529,8 @@ func (ms *MySuite) TestAlphaNumeric(c *C) {
s = "abc!23" s = "abc!23"
err = validator.ValidateFieldByTag(s, "alphanum") err = validator.ValidateFieldByTag(s, "alphanum")
c.Assert(err.Error(), Equals, "alphanum") c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "alphanum")
c.Assert(func() { validator.ValidateFieldByTag(1, "alphanum") }, PanicMatches, "Bad field type int") c.Assert(func() { validator.ValidateFieldByTag(1, "alphanum") }, PanicMatches, "Bad field type int")
} }
@ -526,7 +543,8 @@ func (ms *MySuite) TestAlpha(c *C) {
s = "abc1" s = "abc1"
err = validator.ValidateFieldByTag(s, "alpha") err = validator.ValidateFieldByTag(s, "alpha")
c.Assert(err.Error(), Equals, "alpha") c.Assert(err, NotNil)
c.Assert(err.ErrorTag, Equals, "alpha")
c.Assert(func() { validator.ValidateFieldByTag(1, "alpha") }, PanicMatches, "Bad field type int") c.Assert(func() { validator.ValidateFieldByTag(1, "alpha") }, PanicMatches, "Bad field type int")
} }

Loading…
Cancel
Save