diff --git a/structs.go b/structs.go index 9739f38..be3816a 100644 --- a/structs.go +++ b/structs.go @@ -530,15 +530,22 @@ func (s *Struct) nested(val reflect.Value) interface{} { finalVal = m } case reflect.Map: - v := val.Type().Elem() - if v.Kind() == reflect.Ptr { - v = v.Elem() + // get the element type of the map + mapElem := val.Type() + 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, // map[string][]StructType, - if v.Kind() == reflect.Struct || - (v.Kind() == reflect.Slice && v.Elem().Kind() == reflect.Struct) { + if mapElem.Kind() == reflect.Struct || + (mapElem.Kind() == reflect.Slice && + mapElem.Elem().Kind() == reflect.Struct) { m := make(map[string]interface{}, val.Len()) for _, k := range val.MapKeys() { 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? // do not iterate of non struct types, just pass the value. Ie: []int, // []string, co... We only iterate further if it's a struct. + // i.e []foo or []*foo if val.Type().Elem().Kind() != reflect.Struct && !(val.Type().Elem().Kind() == reflect.Ptr && val.Type().Elem().Elem().Kind() == reflect.Struct) { diff --git a/structs_test.go b/structs_test.go index ea9730d..8a18a07 100644 --- a/structs_test.go +++ b/structs_test.go @@ -1426,3 +1426,28 @@ func TestPointer2Pointer(t *testing.T) { c := &b _ = 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) +}