Skip to content

Commit

Permalink
issue-#14
Browse files Browse the repository at this point in the history
remove internal validator.
  • Loading branch information
Dean Karn authored and Dean Karn committed Mar 11, 2015
1 parent 93115af commit cfea08f
Show file tree
Hide file tree
Showing 4 changed files with 242 additions and 278 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package go-validate-yourself
================
[![Build Status](https://travis-ci.org/joeybloggs/go-validate-yourself.svg?branch=v3-development)](https://travis-ci.org/joeybloggs/go-validate-yourself)
[![Build Status](https://travis-ci.org/joeybloggs/go-validate-yourself.svg?branch=v3)](https://travis-ci.org/joeybloggs/go-validate-yourself)

Package validator implements value validations for structs and individual fields based on tags.

Expand Down
37 changes: 14 additions & 23 deletions doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,12 @@ Package validator implements value validations for structs and individual fields
Built In Validator
The package contains a built in Validator instance for use,
but you may also create a new instance if needed.
v3 no longer contains a built in Validator instance.
// built in
errs := validator.ValidateStruct(//your struct)
valErr := validator.ValidateFieldByTag(field, "omitempty,min=1,max=10")
myValidator = validator.New("validate", validator.BakedInFunctions)
// new
newValidator = validator.New("struct tag name", validator.BakedInFunctions)
errs := myValidator.ValidateStruct(//your struct)
valErr := myValidator.ValidateFieldByTag(field, "omitempty,min=1,max=10")
A simple example usage:
Expand All @@ -32,7 +29,7 @@ A simple example usage:
// errs will contain a hierarchical list of errors
// using the StructValidationErrors struct
// or nil if no errors exist
errs := validator.ValidateStruct(user)
errs := myValidator.ValidateStruct(user)
// in this case 1 error Name is required
errs.Struct will be "User"
Expand Down Expand Up @@ -68,7 +65,7 @@ I needed to know the field and what validation failed so that I could provide an
return "Translated string based on field"
}
The hierarchical structure is hard to work with sometimes.. Agreed Flatten function to the rescue!
The hierarchical error structure is hard to work with sometimes.. Agreed Flatten function to the rescue!
Flatten will return a map of FieldValidationError's but the field name will be namespaced.
// if UserDetail Details field failed validation
Expand All @@ -91,24 +88,24 @@ Custom functions can be added
return true
}
validator.AddFunction("custom tag name", customFunc)
myValidator.AddFunction("custom tag name", customFunc)
// NOTES: using the same tag name as an existing function
// will overwrite the existing one
Cross Field Validation
Cross Field Validation can be implemented, for example Start & End Date range validation
// NOTE: when calling validator.validateStruct(val) val will be the top level struct passed
// NOTE: when calling myValidator.validateStruct(val) val will be the top level struct passed
// into the function
// when calling validator.ValidateFieldByTagAndValue(val, field, tag) val will be
// when calling myValidator.ValidateFieldByTagAndValue(val, field, tag) val will be
// whatever you pass, struct, field...
// when calling validator.ValidateFieldByTag(field, tag) val will be nil
// when calling myValidator.ValidateFieldByTag(field, tag) val will be nil
//
// Because of the specific requirements and field names within each persons project that
// uses this library it is unlikely that any baked in function for this type of validation
// would be added, but you can add your own custom ones and keep all your validation logic
// in one place.
// uses this library it is likely that custom functions will need to be created.
// however there are some build in Generic Cross Field validation, see Baked In Validators and
// Tags below
func isDateRangeValid(val interface{}, field interface{}, param string) bool {
Expand All @@ -121,12 +118,6 @@ Cross Field Validation can be implemented, for example Start & End Date range va
return true
}
Custom Tag Name
A custom tag name can be set to avoid conficts, or just have a shorter name
validator.SetTag("valid")
Multiple Validators
Multiple validators on a field will process in the order defined
Expand Down Expand Up @@ -325,6 +316,6 @@ This package panics when bad input is provided, this is by design, bad code like
TestField: "Test"
}
validator.ValidateStruct(t) // this will panic
myValidator.ValidateStruct(t) // this will panic
*/
package validator
51 changes: 11 additions & 40 deletions validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ import (
)

const (
defaultTagName = "validate"
tagSeparator = ","
orSeparator = "|"
noValidationTag = "-"
tagKeySeparator = "="
omitempty = "omitempty"
validationFieldErrMsg = "Field validation for \"%s\" failed on the \"%s\" tag\n"
validationStructErrMsg = "Struct:%s\n"
Expand Down Expand Up @@ -111,10 +114,6 @@ type Validator struct {
validationFuncs map[string]ValidationFunc
}

// var bakedInValidators = map[string]ValidationFunc{}

var internalValidator = NewValidator(defaultTagName, BakedInValidators)

// 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.
func NewValidator(tagName string, funcs map[string]ValidationFunc) *Validator {
Expand All @@ -124,21 +123,11 @@ func NewValidator(tagName string, funcs map[string]ValidationFunc) *Validator {
}
}

// SetTag sets the baked in Validator's tagName to one of your choosing
func SetTag(tagName string) {
internalValidator.SetTag(tagName)
}

// SetTag sets tagName of the Validator to one of your choosing
func (v *Validator) SetTag(tagName string) {
v.tagName = tagName
}

// AddFunction adds a ValidationFunc to the baked in Validator's map of validators denoted by the key
func AddFunction(key string, f ValidationFunc) error {
return internalValidator.AddFunction(key, f)
}

// AddFunction adds a ValidationFunc to a Validator's map of validators denoted by the key
func (v *Validator) AddFunction(key string, f ValidationFunc) error {

Expand All @@ -160,12 +149,6 @@ func (v *Validator) AddFunction(key string, f ValidationFunc) error {
return nil
}

// ValidateStruct validates a struct and returns a struct containing the errors
func ValidateStruct(s interface{}) *StructValidationErrors {

return internalValidator.ValidateStruct(s)
}

// ValidateStruct validates a struct and returns a struct containing the errors
func (v *Validator) ValidateStruct(s interface{}) *StructValidationErrors {

Expand Down Expand Up @@ -206,7 +189,7 @@ func (v *Validator) validateStructRecursive(top interface{}, s interface{}) *Str

tag := typeField.Tag.Get(v.tagName)

if tag == "-" {
if tag == noValidationTag {
continue
}

Expand Down Expand Up @@ -257,24 +240,12 @@ func (v *Validator) validateStructRecursive(top interface{}, s interface{}) *Str
return validationErrors
}

// 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) *FieldValidationError {

return internalValidator.ValidateFieldByTag(f, tag)
}

// ValidateFieldByTag allows validation of a single field, still using tag style validation to check multiple errors
func (v *Validator) ValidateFieldByTag(f interface{}, tag string) *FieldValidationError {

return v.ValidateFieldByTagAndValue(nil, f, tag)
}

// ValidateFieldByTagAndValue allows validation of a single field with the internal validator, still using tag style validation to check multiple errors
func ValidateFieldByTagAndValue(val interface{}, f interface{}, tag string) *FieldValidationError {

return internalValidator.ValidateFieldByTagAndValue(val, f, tag)
}

// ValidateFieldByTagAndValue allows validation of a single field, still using tag style validation to check multiple errors
func (v *Validator) ValidateFieldByTagAndValue(val interface{}, f interface{}, tag string) *FieldValidationError {

Expand All @@ -284,7 +255,7 @@ func (v *Validator) ValidateFieldByTagAndValue(val interface{}, f interface{}, t
func (v *Validator) validateFieldByNameAndTagAndValue(val interface{}, 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
if tag == "-" {
if tag == noValidationTag {
return nil
}

Expand Down Expand Up @@ -312,11 +283,11 @@ func (v *Validator) validateFieldByNameAndTagAndValue(val interface{}, f interfa

var valErr *FieldValidationError
var err error
valTags := strings.Split(tag, ",")
valTags := strings.Split(tag, tagSeparator)

for _, valTag := range valTags {

orVals := strings.Split(valTag, "|")
orVals := strings.Split(valTag, orSeparator)

if len(orVals) > 1 {

Expand All @@ -330,11 +301,11 @@ func (v *Validator) validateFieldByNameAndTagAndValue(val interface{}, f interfa
return nil
}

errTag += "|" + valErr.ErrorTag
errTag += orSeparator + valErr.ErrorTag

}

errTag = strings.TrimLeft(errTag, "|")
errTag = strings.TrimLeft(errTag, orSeparator)

valErr.ErrorTag = errTag
valErr.Kind = fieldKind
Expand All @@ -356,7 +327,7 @@ func (v *Validator) validateFieldByNameAndTagAndValue(val interface{}, f interfa

func (v *Validator) validateFieldByNameAndSingleTag(val interface{}, f interface{}, name string, valTag string) (*FieldValidationError, error) {

vals := strings.Split(valTag, "=")
vals := strings.Split(valTag, tagKeySeparator)
key := strings.Trim(vals[0], " ")

if len(key) == 0 {
Expand Down
Loading

0 comments on commit cfea08f

Please sign in to comment.