Convert Nested JSON Objects to Python Dataclasses

Learn how to generate multiple Python dataclasses from a JSON object with nested sub-objects. Includes tips on naming, composition, and deserialization.

Dataclasses

Detailed Explanation

Handling Nested JSON with Dataclasses

Real-world JSON is rarely flat. APIs return objects inside objects, and each level of nesting maps to a separate dataclass in Python.

Example JSON

{
  "id": 1,
  "name": "Acme Corp",
  "address": {
    "street": "123 Main St",
    "city": "Springfield",
    "geo": {
      "lat": 39.7817,
      "lng": -89.6501
    }
  }
}

Generated Python

from dataclasses import dataclass

@dataclass
class Geo:
    lat: float
    lng: float

@dataclass
class Address:
    street: str
    city: str
    geo: Geo

@dataclass
class Company:
    id: int
    name: str
    address: Address

Why Separate Dataclasses?

Extracting each nested object into its own dataclass provides:

  1. ReusabilityGeo can be reused wherever coordinates appear (stores, events, deliveries).
  2. Readability — A deeply nested dict is hard to reason about; named classes are self-documenting.
  3. Testability — You can instantiate and test Address independently of Company.

Deserialization

Plain json.loads() returns nested dicts, not dataclass instances. You need a recursive construction step:

import json

data = json.loads(raw_json)
company = Company(
    id=data["id"],
    name=data["name"],
    address=Address(
        street=data["address"]["street"],
        city=data["address"]["city"],
        geo=Geo(**data["address"]["geo"]),
    ),
)

Libraries like dacite or cattrs automate this:

from dacite import from_dict
company = from_dict(data_class=Company, data=data)

Declaration Order

In Python, referenced classes must be defined before the class that uses them (or you use from __future__ import annotations). The converter places leaf classes like Geo first, then Address, then Company.

Use Case

You are integrating with a third-party API that returns deeply nested company data with address and geolocation sub-objects, and you need type-safe access to every level with mypy validation.

Try It — JSON to Python Converter

Open full tool