Reputation: 47
i want to get all keys and values of json fields as type map[string][]string. The objects with same keys, should be in same map field.
I can convert JSON to map[string]interface{} now with this function, but it doesn't meet my needs.
func jsonToMap(data []byte) map[string]interface{} {
x := map[string]interface{}
json.Unmarshal(data, &x)
return x
}
Sample json:
{
"data": {
"name": "John",
"age": 30
},
"items": [
1,
2,
3
],
"data2": {
"name": "Johns",
"age": {
"test": [
1,
2,
3,
{
"test2": "123"
}
]
}
}
}
Expected result:
map[string][]string
map["data"][]string{""}
map["name"][]string{"John", "Johns"}
map["age"][]string{"30",""}
map["items"][]string{"1","2","3"}
map["test"][]string{"1","2","3"}
map["test2"][]string{"123"}
Upvotes: 3
Views: 3292
Reputation: 1525
The solution is using recursive function
.
https://en.wikipedia.org/wiki/Recursion_(computer_science)
Here is a simple example: https://gobyexample.com/recursion
The following code can do what you want:
package main
import (
"encoding/json"
"fmt"
)
func main() {
JSONStr := `{
"data": {"name": "John", "age": 30},
"items": [1, 2, 3],
"data2": {
"name": "Johns",
"age": {"test": [1, 2, 3, {"test2": "123"}]}
}
}`
var JSON map[string]interface{}
json.Unmarshal([]byte(JSONStr), &JSON)
neededOutput := jsonToMap(JSON)
fmt.Println(neededOutput)
}
func jsonToMap(data map[string]interface{}) map[string][]string {
// final output
out := make(map[string][]string)
// check all keys in data
for key, value := range data {
// check if key not exist in out variable, add it
if _, ok := out[key]; !ok {
out[key] = []string{}
}
if valueA, ok := value.(map[string]interface{}); ok { // if value is map
out[key] = append(out[key], "")
for keyB, valueB := range jsonToMap(valueA) {
if _, ok := out[keyB]; !ok {
out[keyB] = []string{}
}
out[keyB] = append(out[keyB], valueB...)
}
} else if valueA, ok := value.([]interface{}); ok { // if value is array
for _, valueB := range valueA {
if valueC, ok := valueB.(map[string]interface{}); ok {
for keyD, valueD := range jsonToMap(valueC) {
if _, ok := out[keyD]; !ok {
out[keyD] = []string{}
}
out[keyD] = append(out[keyD], valueD...)
}
} else {
out[key] = append(out[key], fmt.Sprintf("%v", valueB))
}
}
} else { // if string and numbers and other ...
out[key] = append(out[key], fmt.Sprintf("%v", value))
}
}
return out
}
Output:
map[age:[30 ] data:[] data2:[] items:[1 2 3] name:[John Johns] test:[1 2 3] test2:[123]]
Upvotes: 4