Flatten and Rebuild Nested JSON
Convert nested JSON objects to dotted key paths and reconstruct them, rejecting conflicting paths instead of silently overwriting.
Code
from typing import Any
def flatten(data: dict[str, Any], prefix: str = "") -> dict[str, Any]:
flat: dict[str, Any] = {}
for key, value in data.items():
path = f"{prefix}.{key}" if prefix else key
if isinstance(value, dict) and value:
flat.update(flatten(value, path))
else:
flat[path] = value
return flat
def unflatten(flat: dict[str, Any]) -> dict[str, Any]:
root: dict[str, Any] = {}
for path, value in flat.items():
parts = path.split(".")
cursor = root
for part in parts[:-1]:
existing = cursor.get(part)
if existing is None:
existing = {}
cursor[part] = existing
if not isinstance(existing, dict):
raise ValueError(f"path conflict at {part!r} in {path!r}")
cursor = existing
leaf = parts[-1]
if leaf in cursor:
raise ValueError(f"duplicate or conflicting path: {path!r}")
cursor[leaf] = value
return root
if __name__ == "__main__":
source = {
"server": {"host": "localhost", "ports": [8080, 8081], "tls": {"enabled": True}},
"name": "api",
"empty": {},
}
flat = flatten(source)
print(flat)
print(unflatten(flat) == source)
try:
unflatten({"a": 1, "a.b": 2})
except ValueError as error:
print("rejected:", error)
Report a problem with this exampleOpens a pre-filled issue on GitHub.