Flatten and Rebuild Nested JSON

Convert nested JSON objects to dotted key paths and reconstruct them, rejecting conflicting paths instead of silently overwriting.

PythonData Integrity

Code

snippet
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)