From 3a0791591a10f70e77e48ea874385e34e659103f Mon Sep 17 00:00:00 2001 From: joeybloggs Date: Sun, 16 Aug 2015 10:26:30 -0400 Subject: [PATCH] Add cross struct map support for all types not just string --- util.go | 51 +++++++++++++++++++++++++- validator_test.go | 91 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+), 1 deletion(-) diff --git a/util.go b/util.go index dc612d3..0d3f254 100644 --- a/util.go +++ b/util.go @@ -151,7 +151,56 @@ func (v *Validate) getStructFieldOK(current reflect.Value, namespace string) (re } } - return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(namespace[idx:idx2])), namespace[endIdx+1:]) + key := namespace[idx:idx2] + + switch current.Type().Key().Kind() { + case reflect.Int: + i, _ := strconv.Atoi(key) + return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(i)), namespace[endIdx+1:]) + case reflect.Int8: + i, _ := strconv.ParseInt(key, 10, 8) + return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(int8(i))), namespace[endIdx+1:]) + case reflect.Int16: + i, _ := strconv.ParseInt(key, 10, 16) + return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(int16(i))), namespace[endIdx+1:]) + case reflect.Int32: + i, _ := strconv.ParseInt(key, 10, 32) + return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(int32(i))), namespace[endIdx+1:]) + case reflect.Int64: + i, _ := strconv.ParseInt(key, 10, 64) + return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(i)), namespace[endIdx+1:]) + case reflect.Uint: + i, _ := strconv.ParseUint(key, 10, 0) + return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(uint(i))), namespace[endIdx+1:]) + case reflect.Uint8: + i, _ := strconv.ParseUint(key, 10, 8) + return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(uint8(i))), namespace[endIdx+1:]) + case reflect.Uint16: + i, _ := strconv.ParseUint(key, 10, 16) + return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(uint16(i))), namespace[endIdx+1:]) + case reflect.Uint32: + i, _ := strconv.ParseUint(key, 10, 32) + return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(uint32(i))), namespace[endIdx+1:]) + case reflect.Uint64: + i, _ := strconv.ParseUint(key, 10, 64) + return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(i)), namespace[endIdx+1:]) + case reflect.Float32: + f, _ := strconv.ParseFloat(key, 32) + return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(float32(f))), namespace[endIdx+1:]) + case reflect.Float64: + f, _ := strconv.ParseFloat(key, 64) + return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(f)), namespace[endIdx+1:]) + case reflect.Bool: + b, _ := strconv.ParseBool(key) + return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(b)), namespace[endIdx+1:]) + + // reflect.Type = string + default: + return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(key)), namespace[endIdx+1:]) + } + // v.Type().Key().Kind() + + // return v.getStructFieldOK(current.MapIndex(reflect.ValueOf(key)), namespace[endIdx+1:]) } // if got here there was more namespace, cannot go any deeper diff --git a/validator_test.go b/validator_test.go index 93cdb55..a0dc26a 100644 --- a/validator_test.go +++ b/validator_test.go @@ -318,6 +318,19 @@ func TestCrossNamespaceFieldValidation(t *testing.T) { MapStructs map[string]*SliceStruct MapMapStruct map[string]map[string]*SliceStruct MapSlice map[string][]string + MapInt map[int]string + MapInt8 map[int8]string + MapInt16 map[int16]string + MapInt32 map[int32]string + MapInt64 map[int64]string + MapUint map[uint]string + MapUint8 map[uint8]string + MapUint16 map[uint16]string + MapUint32 map[uint32]string + MapUint64 map[uint64]string + MapFloat32 map[float32]string + MapFloat64 map[float64]string + MapBool map[bool]string } type Test struct { @@ -339,6 +352,19 @@ func TestCrossNamespaceFieldValidation(t *testing.T) { MapMap: map[string]map[string]string{"key1": {"key1-1": "val1"}, "key2": {"key2-1": "val2"}, "key3": {"key3-1": "val3"}}, MapMapStruct: map[string]map[string]*SliceStruct{"key1": {"key1-1": {Name: "name1"}}, "key2": {"key2-1": {Name: "name2"}}, "key3": {"key3-1": {Name: "name3"}}}, MapSlice: map[string][]string{"key1": {"1", "2", "3"}, "key2": {"4", "5", "6"}, "key3": {"7", "8", "9"}}, + MapInt: map[int]string{1: "val1", 2: "val2", 3: "val3"}, + MapInt8: map[int8]string{1: "val1", 2: "val2", 3: "val3"}, + MapInt16: map[int16]string{1: "val1", 2: "val2", 3: "val3"}, + MapInt32: map[int32]string{1: "val1", 2: "val2", 3: "val3"}, + MapInt64: map[int64]string{1: "val1", 2: "val2", 3: "val3"}, + MapUint: map[uint]string{1: "val1", 2: "val2", 3: "val3"}, + MapUint8: map[uint8]string{1: "val1", 2: "val2", 3: "val3"}, + MapUint16: map[uint16]string{1: "val1", 2: "val2", 3: "val3"}, + MapUint32: map[uint32]string{1: "val1", 2: "val2", 3: "val3"}, + MapUint64: map[uint64]string{1: "val1", 2: "val2", 3: "val3"}, + MapFloat32: map[float32]string{1.01: "val1", 2.02: "val2", 3.03: "val3"}, + MapFloat64: map[float64]string{1.01: "val1", 2.02: "val2", 3.03: "val3"}, + MapBool: map[bool]string{true: "val1", false: "val2"}, } test := &Test{ @@ -406,6 +432,71 @@ func TestCrossNamespaceFieldValidation(t *testing.T) { Equal(t, kind, reflect.String) Equal(t, current.String(), "9") + current, kind, ok = validate.getStructFieldOK(val, "Inner.MapInt[2]") + Equal(t, ok, true) + Equal(t, kind, reflect.String) + Equal(t, current.String(), "val2") + + current, kind, ok = validate.getStructFieldOK(val, "Inner.MapInt8[2]") + Equal(t, ok, true) + Equal(t, kind, reflect.String) + Equal(t, current.String(), "val2") + + current, kind, ok = validate.getStructFieldOK(val, "Inner.MapInt16[2]") + Equal(t, ok, true) + Equal(t, kind, reflect.String) + Equal(t, current.String(), "val2") + + current, kind, ok = validate.getStructFieldOK(val, "Inner.MapInt32[2]") + Equal(t, ok, true) + Equal(t, kind, reflect.String) + Equal(t, current.String(), "val2") + + current, kind, ok = validate.getStructFieldOK(val, "Inner.MapInt64[2]") + Equal(t, ok, true) + Equal(t, kind, reflect.String) + Equal(t, current.String(), "val2") + + current, kind, ok = validate.getStructFieldOK(val, "Inner.MapUint[2]") + Equal(t, ok, true) + Equal(t, kind, reflect.String) + Equal(t, current.String(), "val2") + + current, kind, ok = validate.getStructFieldOK(val, "Inner.MapUint8[2]") + Equal(t, ok, true) + Equal(t, kind, reflect.String) + Equal(t, current.String(), "val2") + + current, kind, ok = validate.getStructFieldOK(val, "Inner.MapUint16[2]") + Equal(t, ok, true) + Equal(t, kind, reflect.String) + Equal(t, current.String(), "val2") + + current, kind, ok = validate.getStructFieldOK(val, "Inner.MapUint32[2]") + Equal(t, ok, true) + Equal(t, kind, reflect.String) + Equal(t, current.String(), "val2") + + current, kind, ok = validate.getStructFieldOK(val, "Inner.MapUint64[2]") + Equal(t, ok, true) + Equal(t, kind, reflect.String) + Equal(t, current.String(), "val2") + + current, kind, ok = validate.getStructFieldOK(val, "Inner.MapFloat32[3.03]") + Equal(t, ok, true) + Equal(t, kind, reflect.String) + Equal(t, current.String(), "val3") + + current, kind, ok = validate.getStructFieldOK(val, "Inner.MapFloat64[2.02]") + Equal(t, ok, true) + Equal(t, kind, reflect.String) + Equal(t, current.String(), "val2") + + current, kind, ok = validate.getStructFieldOK(val, "Inner.MapBool[true]") + Equal(t, ok, true) + Equal(t, kind, reflect.String) + Equal(t, current.String(), "val1") + inner = &Inner{ CreatedAt: &now, Slice: []string{"val1", "val2", "val3"},