update to handle nested map + Array + Slice structs

pull/161/head
joeybloggs 9 years ago
parent 3ab458c80c
commit 2ea9043764
  1. 44
      util.go
  2. 34
      validator_test.go

@ -78,8 +78,9 @@ func (v *Validate) getStructFieldOK(current reflect.Value, namespace string) (re
if idx == -1 { if idx == -1 {
ns = namespace[bracketIdx:] ns = namespace[bracketIdx:]
} else { } else {
ns = namespace[idx+bracketIdx:] ns = namespace[bracketIdx:]
} }
// fmt.Println("NSS2:", ns)
} }
// fmt.Println("Looking for field:", fld) // fmt.Println("Looking for field:", fld)
@ -93,6 +94,14 @@ func (v *Validate) getStructFieldOK(current reflect.Value, namespace string) (re
case reflect.Array, reflect.Slice: case reflect.Array, reflect.Slice:
idx := strings.Index(namespace, "[") idx := strings.Index(namespace, "[")
idx2 := strings.Index(namespace, "]") idx2 := strings.Index(namespace, "]")
// idx3 := strings.Index(namespace, namespaceSeparator)
// if idx3 == -1 {
// idx3 = 0
// } else {
// idx3 = 1
// }
//
arrIdx, _ := strconv.Atoi(namespace[idx+1 : idx2]) arrIdx, _ := strconv.Atoi(namespace[idx+1 : idx2])
@ -102,21 +111,36 @@ func (v *Validate) getStructFieldOK(current reflect.Value, namespace string) (re
return current, kind, false return current, kind, false
} }
return v.getStructFieldOK(current.Index(arrIdx), namespace[idx2+1:]) startIdx := idx2 + 1
if startIdx < len(namespace) {
if namespace[startIdx:startIdx+1] == "." {
startIdx++
}
}
return v.getStructFieldOK(current.Index(arrIdx), namespace[startIdx:])
case reflect.Map: case reflect.Map:
idx := strings.Index(namespace, "[") idx := strings.Index(namespace, "[") + 1
idx2 := strings.Index(namespace, "]") idx2 := strings.Index(namespace, "]")
// key, _ := strconv.Atoi(namespace[idx+1 : idx2]) endIdx := idx2
// fmt.Println("ArrayIndex:", arrIdx) // fmt.Println("END IDX:", endIdx)
// fmt.Println("LEN:", current.Len()) // fmt.Println("L NS:", len(namespace))
// if arrIdx >= current.Len() { // fmt.Println("NS:", namespace)
// return current, kind, false
// } if endIdx+1 < len(namespace) {
if namespace[endIdx+1:endIdx+2] == "." {
endIdx++
}
}
// fmt.Println("KEY:", namespace[idx:idx2])
// fmt.Println("KEY NS:", namespace[endIdx+1:])
return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(namespace[idx+1:idx2])), namespace[idx2+1:]) return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(namespace[idx:idx2])), namespace[endIdx+1:])
} }
// fmt.Println("Returning field") // fmt.Println("Returning field")

@ -194,10 +194,20 @@ func ValidateValuerType(field reflect.Value) interface{} {
func TestCrossNamespaceFieldValidation(t *testing.T) { func TestCrossNamespaceFieldValidation(t *testing.T) {
type SliceStruct struct {
Name string
}
type MapStruct struct {
Name string
}
type Inner struct { type Inner struct {
CreatedAt *time.Time CreatedAt *time.Time
Slice []string Slice []string
Map map[string]string SliceStructs []*SliceStruct
Map map[string]string
MapStructs map[string]*SliceStruct
} }
type Test struct { type Test struct {
@ -208,9 +218,11 @@ func TestCrossNamespaceFieldValidation(t *testing.T) {
now := time.Now() now := time.Now()
inner := &Inner{ inner := &Inner{
CreatedAt: &now, CreatedAt: &now,
Slice: []string{"val1", "val2", "val3"}, Slice: []string{"val1", "val2", "val3"},
Map: map[string]string{"key1": "val1", "key2": "val2", "key3": "val3"}, SliceStructs: []*SliceStruct{{Name: "name1"}, {Name: "name2"}, {Name: "name3"}},
Map: map[string]string{"key1": "val1", "key2": "val2", "key3": "val3"},
MapStructs: map[string]*SliceStruct{"key1": {Name: "name1"}, "key2": {Name: "name2"}, "key3": {Name: "name3"}},
} }
test := &Test{ test := &Test{
@ -232,6 +244,9 @@ func TestCrossNamespaceFieldValidation(t *testing.T) {
Equal(t, kind, reflect.String) Equal(t, kind, reflect.String)
Equal(t, current.String(), "val2") Equal(t, current.String(), "val2")
current, kind, ok = validate.getStructFieldOK(val, "Inner.CrazyNonExistantField")
Equal(t, ok, false)
current, kind, ok = validate.getStructFieldOK(val, "Inner.Slice[101]") current, kind, ok = validate.getStructFieldOK(val, "Inner.Slice[101]")
Equal(t, ok, false) Equal(t, ok, false)
@ -240,9 +255,10 @@ func TestCrossNamespaceFieldValidation(t *testing.T) {
Equal(t, kind, reflect.String) Equal(t, kind, reflect.String)
Equal(t, current.String(), "val3") Equal(t, current.String(), "val3")
// fmt.Println(ok) current, kind, ok = validate.getStructFieldOK(val, "Inner.MapStructs[key2].Name")
// fmt.Println(current) Equal(t, ok, true)
// fmt.Println(kind) Equal(t, kind, reflect.String)
Equal(t, current.String(), "name2")
} }
func TestExistsValidation(t *testing.T) { func TestExistsValidation(t *testing.T) {

Loading…
Cancel
Save