Add traverseMap function

pull/114/head
joeybloggs 9 years ago
parent 4d2ffbedfc
commit 88cc19b9e1
  1. 62
      validator.go

@ -12,23 +12,24 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"reflect" "reflect"
"strconv"
"strings" "strings"
"time" "time"
) )
const ( const (
utf8HexComma = "0x2C" utf8HexComma = "0x2C"
utf8Pipe = "0x7C" utf8Pipe = "0x7C"
tagSeparator = "," tagSeparator = ","
orSeparator = "|" orSeparator = "|"
tagKeySeparator = "=" tagKeySeparator = "="
structOnlyTag = "structonly" structOnlyTag = "structonly"
omitempty = "omitempty" omitempty = "omitempty"
skipValidationTag = "-" skipValidationTag = "-"
diveTag = "dive" diveTag = "dive"
fieldErrMsg = "Key: \"%s\" Error:Field validation for \"%s\" failed on the \"%s\" tag" fieldErrMsg = "Key: \"%s\" Error:Field validation for \"%s\" failed on the \"%s\" tag"
invaldField = "Invalid field passed to traverseField" invaldField = "Invalid field passed to traverseField"
arrayIndexFieldName = "%s[%d]"
mapIndexFieldName = "%s[%v]"
) )
var ( var (
@ -133,7 +134,7 @@ func (v *Validate) Struct(current interface{}) ValidationErrors {
errs := map[string]*FieldError{} errs := map[string]*FieldError{}
sv := reflect.ValueOf(current) sv := reflect.ValueOf(current)
v.tranverseStruct(sv, sv, sv, "", errs) v.tranverseStruct(sv, sv, sv, "", errs, true)
if len(errs) == 0 { if len(errs) == 0 {
return nil return nil
@ -142,7 +143,7 @@ func (v *Validate) Struct(current interface{}) ValidationErrors {
return errs return errs
} }
func (v *Validate) tranverseStruct(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, errs ValidationErrors) { func (v *Validate) tranverseStruct(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, errs ValidationErrors, useStructName bool) {
if current.Kind() == reflect.Ptr && !current.IsNil() { if current.Kind() == reflect.Ptr && !current.IsNil() {
current = current.Elem() current = current.Elem()
@ -153,7 +154,11 @@ func (v *Validate) tranverseStruct(topStruct reflect.Value, currentStruct reflec
} }
typ := current.Type() typ := current.Type()
errPrefix += typ.Name() + "."
if useStructName {
errPrefix += typ.Name() + "."
}
numFields := current.NumField() numFields := current.NumField()
var fld reflect.StructField var fld reflect.StructField
@ -246,7 +251,7 @@ func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect.
return return
} }
v.tranverseStruct(topStruct, current, current, errPrefix, errs) v.tranverseStruct(topStruct, current, current, errPrefix+name+".", errs, false)
return return
} }
@ -311,14 +316,17 @@ func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect.
// or panic ;) // or panic ;)
switch kind { switch kind {
case reflect.Slice, reflect.Array: case reflect.Slice, reflect.Array:
case reflect.Map:
v.traverseSlice(topStruct, currentStruct, current, errPrefix, errs, diveSubTag, name) v.traverseSlice(topStruct, currentStruct, current, errPrefix, errs, diveSubTag, name)
case reflect.Map:
v.traverseMap(topStruct, currentStruct, current, errPrefix, errs, diveSubTag, name)
default:
// throw error, if not a slice or map then should not have gotten here
// bad dive tag usage
panic("dive error! can't dive on a non slice or map")
} }
} }
} }
// func (v *Validate) traverseSlice(val interface{}, current interface{}, valueField reflect.Value, cField *cachedField) map[int]error {
func (v *Validate) traverseSlice(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, errs ValidationErrors, tag string, name string) { func (v *Validate) traverseSlice(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, errs ValidationErrors, tag string, name string) {
for i := 0; i < current.Len(); i++ { for i := 0; i < current.Len(); i++ {
@ -329,7 +337,21 @@ func (v *Validate) traverseSlice(topStruct reflect.Value, currentStruct reflect.
idxField = idxField.Elem() idxField = idxField.Elem()
} }
v.traverseField(topStruct, currentStruct, current, errPrefix, errs, false, tag, name+"["+strconv.Itoa(i)+"]") v.traverseField(topStruct, currentStruct, current, errPrefix, errs, false, tag, fmt.Sprintf(arrayIndexFieldName, name, i))
}
}
func (v *Validate) traverseMap(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, errs ValidationErrors, tag string, name string) {
for _, key := range current.MapKeys() {
idxField := current.MapIndex(key)
if idxField.Kind() == reflect.Ptr && !idxField.IsNil() {
idxField = idxField.Elem()
}
v.traverseField(topStruct, currentStruct, current, errPrefix, errs, false, tag, fmt.Sprintf(mapIndexFieldName, name, key.Interface()))
} }
} }

Loading…
Cancel
Save