JSON Flatten / Unflatten
Flatten nested JSON to dot-notation keys, or unflatten dotted keys back to nested objects. Useful for logging pipelines, Elasticsearch, and config management.
Converts nested objects to flat key.path pairs. Arrays become index keys (tags.0, tags.1…).
What is JSON Flattening?
JSON flattening converts a nested JSON object into a flat key-value map where all keys are represented using dot notation. Instead of {"user": {"name": "Ravi"}}, you get {"user.name": "Ravi"}. Unflattening is the reverse — it reconstructs the nested object from dotted keys.
Flattening is used when systems cannot handle nested JSON. Elasticsearch indexes flat field names. Datadog metrics use dot-notation. Environment variable systems like Docker and Kubernetes store config as flat key-value pairs. Relational databases have flat column names. Converting nested JSON to a flat map before passing to these systems avoids mapping errors and simplifies queries.
Flatten vs Unflatten
| Flatten | Unflatten | |
|---|---|---|
| Input | Nested JSON object | Flat JSON with dotted keys |
| Output | Flat key→value map | Nested object |
| Arrays | Indexed as key.0, key.1… | Not reconstructed as arrays |
| Use cases | Elasticsearch, Datadog, env vars, key-value stores | Config parsing, reconstructing from flat storage |
Go — Flatten and Unflatten
// Manual flatten in Go
func flatten(obj map[string]interface{}, prefix string) map[string]interface{} {
result := make(map[string]interface{})
for k, v := range obj {
key := k
if prefix != "" {
key = prefix + "." + k
}
if nested, ok := v.(map[string]interface{}); ok {
for nk, nv := range flatten(nested, key) {
result[nk] = nv
}
} else {
result[key] = v
}
}
return result
}
// Or use a library:
// go get github.com/nqd/flat
import "github.com/nqd/flat"
nested := map[string]interface{}{
"user": map[string]interface{}{
"name": "Ravi",
"address": map[string]interface{}{"city": "Surat"},
},
}
// Flatten
flattened, err := flat.Flatten(nested, &flat.Options{Delimiter: "."})
// => {"user.name": "Ravi", "user.address.city": "Surat"}
// Unflatten
unflattened, err := flat.Unflatten(flattened, &flat.Options{Delimiter: "."})
// => {"user": {"name": "Ravi", "address": {"city": "Surat"}}}Python — Flatten and Unflatten
def flatten(obj, prefix="", sep="."):
result = {}
for k, v in obj.items():
key = f"{prefix}{sep}{k}" if prefix else k
if isinstance(v, dict):
result.update(flatten(v, key, sep))
elif isinstance(v, list):
for i, item in enumerate(v):
if isinstance(item, dict):
result.update(flatten(item, f"{key}{sep}{i}", sep))
else:
result[f"{key}{sep}{i}"] = item
else:
result[key] = v
return result
nested = {"user": {"name": "Ravi", "address": {"city": "Surat"}}, "active": True}
flat = flatten(nested)
# => {"user.name": "Ravi", "user.address.city": "Surat", "active": True}
# Or use the flatten package:
# pip install flatten-dict
from flatten_dict import flatten, unflatten
flat2 = flatten(nested, reducer="dot")
nested2 = unflatten(flat2, splitter="dot")