mirror of
https://github.com/Fishwaldo/validator.git
synced 2025-07-06 04:59:53 +00:00
Merge branch 'v2-development' into v2
Conflicts: validator.go
This commit is contained in:
commit
250bdade04
3 changed files with 205 additions and 112 deletions
104
baked_in.go
104
baked_in.go
|
@ -5,6 +5,7 @@ import (
|
|||
"net/url"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// BakedInValidators is the map of ValidationFunc used internally
|
||||
|
@ -43,9 +44,9 @@ func isURI(val interface{}, field interface{}, param string) bool {
|
|||
_, err := url.ParseRequestURI(field.(string))
|
||||
|
||||
return err == nil
|
||||
default:
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
func isURL(val interface{}, field interface{}, param string) bool {
|
||||
|
@ -66,10 +67,9 @@ func isURL(val interface{}, field interface{}, param string) bool {
|
|||
}
|
||||
|
||||
return err == nil
|
||||
|
||||
default:
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
func isEmail(val interface{}, field interface{}, param string) bool {
|
||||
|
@ -80,9 +80,9 @@ func isEmail(val interface{}, field interface{}, param string) bool {
|
|||
|
||||
case reflect.String:
|
||||
return emailRegex.MatchString(field.(string))
|
||||
default:
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
func isHsla(val interface{}, field interface{}, param string) bool {
|
||||
|
@ -93,9 +93,9 @@ func isHsla(val interface{}, field interface{}, param string) bool {
|
|||
|
||||
case reflect.String:
|
||||
return hslaRegex.MatchString(field.(string))
|
||||
default:
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
func isHsl(val interface{}, field interface{}, param string) bool {
|
||||
|
@ -106,9 +106,9 @@ func isHsl(val interface{}, field interface{}, param string) bool {
|
|||
|
||||
case reflect.String:
|
||||
return hslRegex.MatchString(field.(string))
|
||||
default:
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
func isRgba(val interface{}, field interface{}, param string) bool {
|
||||
|
@ -119,9 +119,9 @@ func isRgba(val interface{}, field interface{}, param string) bool {
|
|||
|
||||
case reflect.String:
|
||||
return rgbaRegex.MatchString(field.(string))
|
||||
default:
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
func isRgb(val interface{}, field interface{}, param string) bool {
|
||||
|
@ -132,9 +132,9 @@ func isRgb(val interface{}, field interface{}, param string) bool {
|
|||
|
||||
case reflect.String:
|
||||
return rgbRegex.MatchString(field.(string))
|
||||
default:
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
func isHexcolor(val interface{}, field interface{}, param string) bool {
|
||||
|
@ -145,9 +145,9 @@ func isHexcolor(val interface{}, field interface{}, param string) bool {
|
|||
|
||||
case reflect.String:
|
||||
return hexcolorRegex.MatchString(field.(string))
|
||||
default:
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
func isHexadecimal(val interface{}, field interface{}, param string) bool {
|
||||
|
@ -158,9 +158,9 @@ func isHexadecimal(val interface{}, field interface{}, param string) bool {
|
|||
|
||||
case reflect.String:
|
||||
return hexadecimalRegex.MatchString(field.(string))
|
||||
default:
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
func isNumber(val interface{}, field interface{}, param string) bool {
|
||||
|
@ -171,9 +171,9 @@ func isNumber(val interface{}, field interface{}, param string) bool {
|
|||
|
||||
case reflect.String:
|
||||
return numberRegex.MatchString(field.(string))
|
||||
default:
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
func isNumeric(val interface{}, field interface{}, param string) bool {
|
||||
|
@ -184,9 +184,9 @@ func isNumeric(val interface{}, field interface{}, param string) bool {
|
|||
|
||||
case reflect.String:
|
||||
return numericRegex.MatchString(field.(string))
|
||||
default:
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
func isAlphanum(val interface{}, field interface{}, param string) bool {
|
||||
|
@ -197,9 +197,9 @@ func isAlphanum(val interface{}, field interface{}, param string) bool {
|
|||
|
||||
case reflect.String:
|
||||
return alphaNumericRegex.MatchString(field.(string))
|
||||
default:
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
func isAlpha(val interface{}, field interface{}, param string) bool {
|
||||
|
@ -210,9 +210,9 @@ func isAlpha(val interface{}, field interface{}, param string) bool {
|
|||
|
||||
case reflect.String:
|
||||
return alphaRegex.MatchString(field.(string))
|
||||
default:
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
func hasValue(val interface{}, field interface{}, param string) bool {
|
||||
|
@ -260,9 +260,18 @@ func isGte(val interface{}, field interface{}, param string) bool {
|
|||
|
||||
return st.Float() >= p
|
||||
|
||||
default:
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
case reflect.Struct:
|
||||
|
||||
if st.Type() == reflect.TypeOf(field) {
|
||||
|
||||
now := time.Now().UTC()
|
||||
t := field.(time.Time)
|
||||
|
||||
return t.After(now) || t.Equal(now)
|
||||
}
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
func isGt(val interface{}, field interface{}, param string) bool {
|
||||
|
@ -295,10 +304,15 @@ func isGt(val interface{}, field interface{}, param string) bool {
|
|||
p := asFloat(param)
|
||||
|
||||
return st.Float() > p
|
||||
case reflect.Struct:
|
||||
|
||||
default:
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
if st.Type() == reflect.TypeOf(field) {
|
||||
|
||||
return field.(time.Time).After(time.Now().UTC())
|
||||
}
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
// length tests whether a variable's length is equal to a given
|
||||
|
@ -334,10 +348,9 @@ func hasLengthOf(val interface{}, field interface{}, param string) bool {
|
|||
p := asFloat(param)
|
||||
|
||||
return st.Float() == p
|
||||
|
||||
default:
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
// min tests whether a variable value is larger or equal to a given
|
||||
|
@ -380,9 +393,18 @@ func isLte(val interface{}, field interface{}, param string) bool {
|
|||
|
||||
return st.Float() <= p
|
||||
|
||||
default:
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
case reflect.Struct:
|
||||
|
||||
if st.Type() == reflect.TypeOf(field) {
|
||||
|
||||
now := time.Now().UTC()
|
||||
t := field.(time.Time)
|
||||
|
||||
return t.Before(now) || t.Equal(now)
|
||||
}
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
func isLt(val interface{}, field interface{}, param string) bool {
|
||||
|
@ -416,9 +438,15 @@ func isLt(val interface{}, field interface{}, param string) bool {
|
|||
|
||||
return st.Float() < p
|
||||
|
||||
default:
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
case reflect.Struct:
|
||||
|
||||
if st.Type() == reflect.TypeOf(field) {
|
||||
|
||||
return field.(time.Time).Before(time.Now().UTC())
|
||||
}
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("Bad field type %T", field))
|
||||
}
|
||||
|
||||
// max tests whether a variable value is lesser than a given
|
||||
|
|
94
validator.go
94
validator.go
|
@ -13,6 +13,7 @@ import (
|
|||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
|
@ -174,75 +175,6 @@ func (v *Validator) ValidateStruct(s interface{}) *StructValidationErrors {
|
|||
}
|
||||
|
||||
return v.validateStructRecursive(s, s)
|
||||
// structValue := reflect.ValueOf(s)
|
||||
// structType := reflect.TypeOf(s)
|
||||
// structName := structType.Name()
|
||||
|
||||
// validationErrors := &StructValidationErrors{
|
||||
// Struct: structName,
|
||||
// Errors: map[string]*FieldValidationError{},
|
||||
// StructErrors: map[string]*StructValidationErrors{},
|
||||
// }
|
||||
|
||||
// if structValue.Kind() == reflect.Ptr && !structValue.IsNil() {
|
||||
// return v.ValidateStruct(structValue.Elem().Interface())
|
||||
// }
|
||||
|
||||
// if structValue.Kind() != reflect.Struct && structValue.Kind() != reflect.Interface {
|
||||
// panic("interface passed for validation is not a struct")
|
||||
// }
|
||||
|
||||
// var numFields = structValue.NumField()
|
||||
|
||||
// for i := 0; i < numFields; i++ {
|
||||
|
||||
// valueField := structValue.Field(i)
|
||||
// typeField := structType.Field(i)
|
||||
|
||||
// if valueField.Kind() == reflect.Ptr && !valueField.IsNil() {
|
||||
// valueField = valueField.Elem()
|
||||
// }
|
||||
|
||||
// tag := typeField.Tag.Get(v.tagName)
|
||||
|
||||
// if tag == "-" {
|
||||
// continue
|
||||
// }
|
||||
|
||||
// // if no validation and not a struct (which may containt fields for validation)
|
||||
// if tag == "" && valueField.Kind() != reflect.Struct && valueField.Kind() != reflect.Interface {
|
||||
// continue
|
||||
// }
|
||||
|
||||
// switch valueField.Kind() {
|
||||
|
||||
// case reflect.Struct, reflect.Interface:
|
||||
|
||||
// if !unicode.IsUpper(rune(typeField.Name[0])) {
|
||||
// continue
|
||||
// }
|
||||
|
||||
// if structErrors := v.ValidateStruct(valueField.Interface()); structErrors != nil {
|
||||
// validationErrors.StructErrors[typeField.Name] = structErrors
|
||||
// // free up memory map no longer needed
|
||||
// structErrors = nil
|
||||
// }
|
||||
|
||||
// default:
|
||||
|
||||
// if fieldError := v.validateFieldByNameAndTag(valueField.Interface(), typeField.Name, tag); fieldError != nil {
|
||||
// validationErrors.Errors[fieldError.Field] = fieldError
|
||||
// // free up memory reference
|
||||
// fieldError = nil
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// if len(validationErrors.Errors) == 0 && len(validationErrors.StructErrors) == 0 {
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// return validationErrors
|
||||
}
|
||||
|
||||
// validateStructRecursive validates a struct recursivly and passes the top level struct around for use in validator functions and returns a struct containing the errors
|
||||
|
@ -296,10 +228,21 @@ func (v *Validator) validateStructRecursive(top interface{}, s interface{}) *Str
|
|||
continue
|
||||
}
|
||||
|
||||
if structErrors := v.validateStructRecursive(top, valueField.Interface()); structErrors != nil {
|
||||
validationErrors.StructErrors[typeField.Name] = structErrors
|
||||
// free up memory map no longer needed
|
||||
structErrors = nil
|
||||
if valueField.Type() == reflect.TypeOf(time.Time{}) {
|
||||
|
||||
if fieldError := v.validateFieldByNameAndTagAndValue(top, valueField.Interface(), typeField.Name, tag); fieldError != nil {
|
||||
validationErrors.Errors[fieldError.Field] = fieldError
|
||||
// free up memory reference
|
||||
fieldError = nil
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if structErrors := v.ValidateStruct(valueField.Interface()); structErrors != nil {
|
||||
validationErrors.StructErrors[typeField.Name] = structErrors
|
||||
// free up memory map no longer needed
|
||||
structErrors = nil
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
|
@ -363,7 +306,10 @@ func (v *Validator) validateFieldByNameAndTagAndValue(val interface{}, f interfa
|
|||
switch valueField.Kind() {
|
||||
|
||||
case reflect.Struct, reflect.Interface, reflect.Invalid:
|
||||
panic("Invalid field passed to ValidateFieldWithTag")
|
||||
|
||||
if valueField.Type() != reflect.TypeOf(time.Time{}) {
|
||||
panic("Invalid field passed to ValidateFieldWithTag")
|
||||
}
|
||||
}
|
||||
|
||||
var valErr *FieldValidationError
|
||||
|
|
|
@ -3,6 +3,7 @@ package validator_test
|
|||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/joeybloggs/go-validate-yourself"
|
||||
. "gopkg.in/check.v1"
|
||||
|
@ -242,12 +243,70 @@ func (ms *MySuite) TestIsGt(c *C) {
|
|||
|
||||
i := true
|
||||
c.Assert(func() { validator.ValidateFieldByTag(i, "gt") }, PanicMatches, "Bad field type bool")
|
||||
|
||||
t := time.Now().UTC()
|
||||
t = t.Add(time.Hour * 24)
|
||||
|
||||
err = validator.ValidateFieldByTag(t, "gt")
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
t2 := time.Now().UTC()
|
||||
|
||||
err = validator.ValidateFieldByTag(t2, "gt")
|
||||
c.Assert(err, NotNil)
|
||||
c.Assert(err.ErrorTag, Equals, "gt")
|
||||
|
||||
type Test struct {
|
||||
Now *time.Time `validate:"gt"`
|
||||
}
|
||||
s := &Test{
|
||||
Now: &t,
|
||||
}
|
||||
|
||||
errs := validator.ValidateStruct(s)
|
||||
c.Assert(errs, IsNil)
|
||||
|
||||
s = &Test{
|
||||
Now: &t2,
|
||||
}
|
||||
|
||||
errs = validator.ValidateStruct(s)
|
||||
c.Assert(errs, NotNil)
|
||||
}
|
||||
|
||||
func (ms *MySuite) TestIsGte(c *C) {
|
||||
|
||||
i := true
|
||||
c.Assert(func() { validator.ValidateFieldByTag(i, "gte") }, PanicMatches, "Bad field type bool")
|
||||
|
||||
t := time.Now().UTC()
|
||||
t = t.Add(time.Hour * 24)
|
||||
|
||||
err := validator.ValidateFieldByTag(t, "gte")
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
t2 := time.Now().UTC()
|
||||
|
||||
err = validator.ValidateFieldByTag(t2, "gte")
|
||||
c.Assert(err, NotNil)
|
||||
c.Assert(err.ErrorTag, Equals, "gte")
|
||||
|
||||
type Test struct {
|
||||
Now *time.Time `validate:"gte"`
|
||||
}
|
||||
s := &Test{
|
||||
Now: &t,
|
||||
}
|
||||
|
||||
errs := validator.ValidateStruct(s)
|
||||
c.Assert(errs, IsNil)
|
||||
|
||||
s = &Test{
|
||||
Now: &t2,
|
||||
}
|
||||
|
||||
errs = validator.ValidateStruct(s)
|
||||
c.Assert(errs, NotNil)
|
||||
}
|
||||
|
||||
func (ms *MySuite) TestIsLt(c *C) {
|
||||
|
@ -266,12 +325,72 @@ func (ms *MySuite) TestIsLt(c *C) {
|
|||
|
||||
i := true
|
||||
c.Assert(func() { validator.ValidateFieldByTag(i, "lt") }, PanicMatches, "Bad field type bool")
|
||||
|
||||
t := time.Now().UTC()
|
||||
|
||||
err = validator.ValidateFieldByTag(t, "lt")
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
t2 := time.Now().UTC()
|
||||
t2 = t2.Add(time.Hour * 24)
|
||||
|
||||
err = validator.ValidateFieldByTag(t2, "lt")
|
||||
c.Assert(err, NotNil)
|
||||
c.Assert(err.ErrorTag, Equals, "lt")
|
||||
|
||||
type Test struct {
|
||||
Now *time.Time `validate:"lt"`
|
||||
}
|
||||
|
||||
s := &Test{
|
||||
Now: &t,
|
||||
}
|
||||
|
||||
errs := validator.ValidateStruct(s)
|
||||
c.Assert(errs, IsNil)
|
||||
|
||||
s = &Test{
|
||||
Now: &t2,
|
||||
}
|
||||
|
||||
errs = validator.ValidateStruct(s)
|
||||
c.Assert(errs, NotNil)
|
||||
}
|
||||
|
||||
func (ms *MySuite) TestIsLte(c *C) {
|
||||
|
||||
i := true
|
||||
c.Assert(func() { validator.ValidateFieldByTag(i, "lte") }, PanicMatches, "Bad field type bool")
|
||||
|
||||
t := time.Now().UTC()
|
||||
|
||||
err := validator.ValidateFieldByTag(t, "lte")
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
t2 := time.Now().UTC()
|
||||
t2 = t2.Add(time.Hour * 24)
|
||||
|
||||
err = validator.ValidateFieldByTag(t2, "lte")
|
||||
c.Assert(err, NotNil)
|
||||
c.Assert(err.ErrorTag, Equals, "lte")
|
||||
|
||||
type Test struct {
|
||||
Now *time.Time `validate:"lte"`
|
||||
}
|
||||
|
||||
s := &Test{
|
||||
Now: &t,
|
||||
}
|
||||
|
||||
errs := validator.ValidateStruct(s)
|
||||
c.Assert(errs, IsNil)
|
||||
|
||||
s = &Test{
|
||||
Now: &t2,
|
||||
}
|
||||
|
||||
errs = validator.ValidateStruct(s)
|
||||
c.Assert(errs, NotNil)
|
||||
}
|
||||
|
||||
func (ms *MySuite) TestUrl(c *C) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue