How to convert interface{} to map
Solution 1
If the map value can be any type, then use reflect to iterate through the map:
if v.Kind() == reflect.Map {
for _, key := range v.MapKeys() {
strct := v.MapIndex(key)
fmt.Println(key.Interface(), strct.Interface())
}
}
If there's a small and known set of struct types, then a type switch can be used:
func process(in interface{}) {
switch v := in.(type) {
case map[string]*Book:
for s, b := range v {
// b has type *Book
fmt.Printf("%s: book=%v\n" s, b)
}
case map[string]*Author:
for s, a := range v {
// a has type *Author
fmt.Printf("%s: author=%v\n" s, a)
}
case []*Book:
for i, b := range v {
fmt.Printf("%d: book=%v\n" i, b)
}
case []*Author:
for i, a := range v {
fmt.Printf("%d: author=%v\n" i, a)
}
case *Book:
fmt.Ptintf("book=%v\n", v)
case *Author:
fmt.Printf("author=%v\n", v)
default:
// handle unknown type
}
}
Solution 2
You don't need reflect here. Try:
v, ok := in.(map[string]*Book)
if !ok {
// Can't assert, handle error.
}
for _, s := range v {
fmt.Printf("Value: %v\n", s)
}
Same goes for the rest of your function. It looks like you're using reflection when you would be better served by a type switch.
Alternatively, if you insist on using reflection here (which doesn't make a lot of sense) you can also use Value.MapKeys
with the result from your ValueOf (see the answer https://stackoverflow.com/a/38186057/714501)
Solution 3
This may help:
b := []byte(`{"keyw":"value"}`)
var f interface{}
json.Unmarshal(b, &f)
myMap := f.(map[string]interface{})
fmt.Println(myMap)
SamTech
Updated on July 09, 2022Comments
-
SamTech almost 2 years
I am trying to create a function that could accept following
*struct []*struct map[string]*struct
Here struct could be any struct not just a specific one. Converting interface to
*struct
or[]*struct
is working fine. But giving error for map.After reflect it shows it is map[] but giving error when try to iterate over range.
Here is code
package main import ( "fmt" "reflect" ) type Book struct { ID int Title string Year int } func process(in interface{}, isSlice bool, isMap bool) { v := reflect.ValueOf(in) if isSlice { for i := 0; i < v.Len(); i++ { strct := v.Index(i).Interface() //... proccess struct } return } if isMap { fmt.Printf("Type: %v\n", v) // map[] for _, s := range v { // Error: cannot range over v (type reflect.Value) fmt.Printf("Value: %v\n", s.Interface()) } } } func main() { b := Book{} b.Title = "Learn Go Language" b.Year = 2014 m := make(map[string]*Book) m["1"] = &b process(m, false, true) }
Is there any way to convert
interface{}
to map and iterate or get it's elements. -
cnicutar almost 8 yearsNice. I added the
MapKeys
to my answer part as you were posting yours! -
SamTech almost 8 yearsWorking absolutely fine. Thanks a lot.
-
SamTech almost 8 yearsHere struct could be any struct like Book, Auther, Publisher ... for type switching type of struct must be known, that i don't have.
-
cnicutar almost 8 years@SamTech How is the type of the struct not "known"? You can just switch over all the types you want to handle.
-
SamTech almost 8 yearsI mean, how do i know whether i have to type switch passed interface to map[string]*Book or map[string]*Auther ?
-
cnicutar almost 8 years@SamTech Just switch on both.