initial code

checkin so that can integrate with http://gopkg.in/
pull/16/head
Dean Karn 10 years ago
parent 2483ffe407
commit c0ff4f7f60
  1. 127
      validator.go
  2. 31
      validator_test.go

@ -0,0 +1,127 @@
package validator
import (
"errors"
"fmt"
"log"
"reflect"
)
// FieldValidationError contains a single fields validation error
type FieldValidationError struct {
Field string
ErrorTag string
}
// StructValidationErrors is a slice of errors for struct fields ( Excluding struct fields)
// 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 ArrayValidationErrors is created for each struct
type StructValidationErrors struct {
Errors []FieldValidationError
}
// ArrayStructValidationErrors is a struct that contains a 2D flattened list of struct specific StructValidationErrors
type ArrayStructValidationErrors struct {
// Key = Struct Name
Errors map[string][]StructValidationErrors
}
// 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) error
// Validator implements the Validator Struct
// NOTE: Fields within are not thread safe and that is on purpose
// Functions Tags etc. should all be predifined before use, so subscribe to the philosiphy
// or make it thread safe on your end
type Validator struct {
// TagName being used.
tagName string
// validationFuncs is a map of validation functions and the tag keys
validationFuncs map[string]ValidationFunc
}
var bakedInValidators = map[string]ValidationFunc{}
var internalValidator = NewValidator("validate", 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 {
return &Validator{
tagName: tagName,
validationFuncs: funcs,
}
}
// 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 {
if len(key) == 0 {
return errors.New("Function Key cannot be empty")
}
if f == nil {
return errors.New("Function Key cannot be empty")
}
// Commented out to allow overwritting of Baked In Function if so desired.
// if v.ValidationFuncs[key] != nil {
// return errors.New(fmt.Sprintf("Validation Function with key: %s already exists.", key))
// }
v.validationFuncs[key] = f
return nil
}
func ValidateStruct(s interface{}) ArrayStructValidationErrors {
return internalValidator.ValidateStruct(s)
}
func (v *Validator) ValidateStruct(s interface{}) ArrayStructValidationErrors {
var errorStruct = ArrayStructValidationErrors{}
structValue := reflect.ValueOf(s)
structType := reflect.TypeOf(s)
if structValue.Kind() == reflect.Ptr && !structValue.IsNil() {
return v.ValidateStruct(structValue.Elem().Interface())
}
if structValue.Kind() != reflect.Struct {
log.Fatal("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()
}
fmt.Println(typeField.Name)
}
return errorStruct
}

@ -0,0 +1,31 @@
package validator_test
import (
"fmt"
"testing"
"github.com/joeybloggs/go-validate-yourself"
)
type UserDetails struct {
Address string `validate:"required"`
}
type User struct {
FirstName string `validate:"required"`
Details *UserDetails
}
func TestValidateStruct(t *testing.T) {
u := &User{
FirstName: "Dean Karn",
Details: &UserDetails{
"26 Here Blvd.",
},
}
errors := validator.ValidateStruct(u)
fmt.Println(errors)
}
Loading…
Cancel
Save