My app needs to take a large array of nested instances of map[string]interface{} and turn them into flattened maps.
For example:
{
"foo": {
"jim":"bean"
},
"fee": "bar",
"n1": {
"alist": [
"a",
"b",
"c",
{
"d": "other",
"e": "another"
}
]
},
"number": 1.4567,
"bool": true
}
After:
json.Unmarshal([]byte(input), &out)
result = Flatten(m.(map[string]interface{}))
Becomes:
{
"foo.jim": "bean",
"fee": "bar",
"n1.alist.0": "a",
"n1.alist.1": "b",
"n1.alist.2": "c",
"n1.alist.3.d": "other",
"n1.alist.3.e": "another",
"number": 1.4567,
"bool": true,
}
Currently I am using the below code:
func Flatten(m map[string]interface{}) map[string]interface{} {
o := map[string]interface{}{}
for k, v := range m {
switch child := v.(type) {
case map[string]interface{}:
nm := Flatten(child)
for nk, nv := range nm {
o[k+"."+nk] = nv
}
case []interface{}:
for i := 0; i < len(child); i++ {
o[k+"."+strconv.Itoa(i)] = child[i]
}
default:
o[k] = v
}
}
return o
}
This code is very memory inefficient, when flatting ~800 maps, ~8 GiB memory is used. I have tried passing pointers instead of copies, but that does not change the memory usage. Do I have to do some type of manual memory management? Go should garbage collect any unused memory, but it might be that I am not releasing it somehow.