Currently I'm using the following code to convert nested json into flattened json:
import (
"fmt"
"github.com/nytlabs/gojsonexplode"
)
func main() {
input := `{"person":{"name":"Joe", "address":{"street":"123 Main St."}}}`
out, err := gojsonexplode.Explodejsonstr(input, ".")
if err != nil {
// handle error
}
fmt.Println(out)
}
This is the output: {"person.address.street":"123 Main St.","person.name":"Joe"}
After some processing, now I want to restore this data into normal nested json, but I'm unable to do so.
My closest guess is usage of nested maps, but I don't know how to create nested map with N levels.
EDIT: Reason why I need this: I'm storing data in Redis, and if I store json into Redis then I can't search for keys, that's why I convert keys into key1:key2:key3: some_value
In order to "unflatten" the data you need to split each of the keys at the dot and create nested objects. Here is an example with your data on the Go Playground.
func unflatten(flat map[string]interface{}) (map[string]interface{}, error) {
unflat := map[string]interface{}{}
for key, value := range flat {
keyParts := strings.Split(key, ".")
// Walk the keys until we get to a leaf node.
m := unflat
for i, k := range keyParts[:len(keyParts)-1] {
v, exists := m[k]
if !exists {
newMap := map[string]interface{}{}
m[k] = newMap
m = newMap
continue
}
innerMap, ok := v.(map[string]interface{})
if !ok {
return nil, fmt.Errorf("key=%v is not an object", strings.Join(keyParts[0:i+1], "."))
}
m = innerMap
}
leafKey := keyParts[len(keyParts)-1]
if _, exists := m[leafKey]; exists {
return nil, fmt.Errorf("key=%v already exists", key)
}
m[keyParts[len(keyParts)-1]] = value
}
return unflat, nil
}
json.MarshalIndent is your friend.
j, err := json.MarshalIndent(x, "", "\t")
if err != nil {
log.Println(err)
}
log.Println(string(j))
It will print your data (x) in indented manner.