From 2ea9043764be53679393bf021e233d5f414172ff Mon Sep 17 00:00:00 2001 From: joeybloggs Date: Fri, 14 Aug 2015 00:28:37 -0400 Subject: [PATCH] update to handle nested map + Array + Slice structs --- util.go | 44 ++++++++++++++++++++++++++++++++++---------- validator_test.go | 34 +++++++++++++++++++++++++--------- 2 files changed, 59 insertions(+), 19 deletions(-) diff --git a/util.go b/util.go index 7d55550..4dd39ba 100644 --- a/util.go +++ b/util.go @@ -78,8 +78,9 @@ func (v *Validate) getStructFieldOK(current reflect.Value, namespace string) (re if idx == -1 { ns = namespace[bracketIdx:] } else { - ns = namespace[idx+bracketIdx:] + ns = namespace[bracketIdx:] } + // fmt.Println("NSS2:", ns) } // 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: idx := 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]) @@ -102,21 +111,36 @@ func (v *Validate) getStructFieldOK(current reflect.Value, namespace string) (re 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: - idx := strings.Index(namespace, "[") + idx := strings.Index(namespace, "[") + 1 idx2 := strings.Index(namespace, "]") - // key, _ := strconv.Atoi(namespace[idx+1 : idx2]) + endIdx := idx2 - // fmt.Println("ArrayIndex:", arrIdx) - // fmt.Println("LEN:", current.Len()) - // if arrIdx >= current.Len() { - // return current, kind, false - // } + // fmt.Println("END IDX:", endIdx) + // fmt.Println("L NS:", len(namespace)) + // fmt.Println("NS:", namespace) + + 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") diff --git a/validator_test.go b/validator_test.go index ccd9a9b..761e3bf 100644 --- a/validator_test.go +++ b/validator_test.go @@ -194,10 +194,20 @@ func ValidateValuerType(field reflect.Value) interface{} { func TestCrossNamespaceFieldValidation(t *testing.T) { + type SliceStruct struct { + Name string + } + + type MapStruct struct { + Name string + } + type Inner struct { - CreatedAt *time.Time - Slice []string - Map map[string]string + CreatedAt *time.Time + Slice []string + SliceStructs []*SliceStruct + Map map[string]string + MapStructs map[string]*SliceStruct } type Test struct { @@ -208,9 +218,11 @@ func TestCrossNamespaceFieldValidation(t *testing.T) { now := time.Now() inner := &Inner{ - CreatedAt: &now, - Slice: []string{"val1", "val2", "val3"}, - Map: map[string]string{"key1": "val1", "key2": "val2", "key3": "val3"}, + CreatedAt: &now, + Slice: []string{"val1", "val2", "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{ @@ -232,6 +244,9 @@ func TestCrossNamespaceFieldValidation(t *testing.T) { Equal(t, kind, reflect.String) 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]") Equal(t, ok, false) @@ -240,9 +255,10 @@ func TestCrossNamespaceFieldValidation(t *testing.T) { Equal(t, kind, reflect.String) Equal(t, current.String(), "val3") - // fmt.Println(ok) - // fmt.Println(current) - // fmt.Println(kind) + current, kind, ok = validate.getStructFieldOK(val, "Inner.MapStructs[key2].Name") + Equal(t, ok, true) + Equal(t, kind, reflect.String) + Equal(t, current.String(), "name2") } func TestExistsValidation(t *testing.T) {