Reputation: 1186
My code is getting plastered with functions like the following:
func TransformMapClassA(mapOfIntToClassA map[int]*ClassA) map[string]*ClassA {
mapOfStringToClassA := make(map[string]*ClassA)
for id, obj := range mapOfIntToClassA {
mapOfStringToClassA[fmt.Sprintf("%d" obj.Id)] = obj
}
return mapOfStringToClassA
}
written once for each class in my application. I'm doing this, so I can json.Marshal the existing map. Is there a generic way of doing this, so I don't have to write one function per class? I've tried doing things like:
type Int64JSON int64 `json:",string"`
and using Int64JSON in my original maps, but the compiler doesn't like the json tag in a type definition :(
Many thanks in advance!
Upvotes: 2
Views: 104
Reputation: 77935
If you still want to use reflection to create a function that returns a map[string]interface{} from any type of map, you can do the following:
func TransformMap(m interface{}) (map[string]interface{}, error) {
v := reflect.ValueOf(m)
if v.Kind() != reflect.Map {
return nil, errors.New("Map required")
}
result := make(map[string]interface{}, v.Len())
keys := v.MapKeys()
for _, k := range keys {
result[fmt.Sprint(k.Interface())] = v.MapIndex(k).Interface()
}
return result, nil
}
Upvotes: 2
Reputation: 22991
There are a number of ways you can do that. One of them is using a generic map[interface{}]interface{}
, and having a conversion function such as:
func stringMap(m map[interface{}]interface{}) map[string]interface{} {
result := make(map[string]interface{})
for k, v := range m {
result[fmt.Sprint(k)] = v
}
return result
}
(on play)
You might also use reflection, etc.
That said, before doing any of that, I'd ponder whether it's really so much burden to do that for the real types. There are several benefits in having proper typing (type checking, no need for assertions when reading, performance, memory use, etc), and it's a fairly small amount of code.
Upvotes: 1