structs: fix interface{} type with map values

Fixes #76
This commit is contained in:
Fatih Arslan 2016-08-07 19:55:29 -04:00
parent bf7dff7189
commit 1fe66a405b
2 changed files with 38 additions and 5 deletions

View File

@ -530,15 +530,22 @@ func (s *Struct) nested(val reflect.Value) interface{} {
finalVal = m finalVal = m
} }
case reflect.Map: case reflect.Map:
v := val.Type().Elem() // get the element type of the map
if v.Kind() == reflect.Ptr { mapElem := val.Type()
v = v.Elem() switch val.Type().Kind() {
case reflect.Ptr, reflect.Array, reflect.Map,
reflect.Slice, reflect.Chan:
mapElem = val.Type().Elem()
if mapElem.Kind() == reflect.Ptr {
mapElem = mapElem.Elem()
}
} }
// only iterate over struct types, ie: map[string]StructType, // only iterate over struct types, ie: map[string]StructType,
// map[string][]StructType, // map[string][]StructType,
if v.Kind() == reflect.Struct || if mapElem.Kind() == reflect.Struct ||
(v.Kind() == reflect.Slice && v.Elem().Kind() == reflect.Struct) { (mapElem.Kind() == reflect.Slice &&
mapElem.Elem().Kind() == reflect.Struct) {
m := make(map[string]interface{}, val.Len()) m := make(map[string]interface{}, val.Len())
for _, k := range val.MapKeys() { for _, k := range val.MapKeys() {
m[k.String()] = s.nested(val.MapIndex(k)) m[k.String()] = s.nested(val.MapIndex(k))
@ -558,6 +565,7 @@ func (s *Struct) nested(val reflect.Value) interface{} {
// TODO(arslan): should this be optional? // TODO(arslan): should this be optional?
// do not iterate of non struct types, just pass the value. Ie: []int, // do not iterate of non struct types, just pass the value. Ie: []int,
// []string, co... We only iterate further if it's a struct. // []string, co... We only iterate further if it's a struct.
// i.e []foo or []*foo
if val.Type().Elem().Kind() != reflect.Struct && if val.Type().Elem().Kind() != reflect.Struct &&
!(val.Type().Elem().Kind() == reflect.Ptr && !(val.Type().Elem().Kind() == reflect.Ptr &&
val.Type().Elem().Elem().Kind() == reflect.Struct) { val.Type().Elem().Elem().Kind() == reflect.Struct) {

View File

@ -1426,3 +1426,28 @@ func TestPointer2Pointer(t *testing.T) {
c := &b c := &b
_ = Map(&c) _ = Map(&c)
} }
func TestMap_InterfaceTypeWithMapValue(t *testing.T) {
type A struct {
Name string `structs:"name"`
Ip string `structs:"ip"`
Query string `structs:"query"`
Payload interface{} `structs:"payload"`
}
a := A{
Name: "test",
Ip: "127.0.0.1",
Query: "",
Payload: map[string]string{"test_param": "test_param"},
}
defer func() {
err := recover()
if err != nil {
t.Error("Converting Map with an interface{} type with map value should not panic")
}
}()
_ = Map(a)
}