JSON Lark

Sheet 03 Python classes

JSON to Python

Paste JSON samples and get dataclasses, Pydantic v2 models or TypedDicts, with snake_case attributes that still map to your original keys.

JSON

Python

from dataclasses import dataclass
from typing import Any


@dataclass
class Address:
    street: str
    city: str
    zip_code: str

    @classmethod
    def from_dict(cls, data: dict[str, Any]) -> "Address":
        return cls(
            street=data["street"],
            city=data["city"],
            zip_code=data["zipCode"],
        )


@dataclass
class Project:
    name: str
    year: int
    role: str | None = None

    @classmethod
    def from_dict(cls, data: dict[str, Any]) -> "Project":
        return cls(
            name=data["name"],
            year=data["year"],
            role=data.get("role"),
        )


@dataclass
class Root:
    user_id: int
    user_name: str
    is_admin: bool
    last_login: str
    address: Address
    projects: list[Project]

    @classmethod
    def from_dict(cls, data: dict[str, Any]) -> "Root":
        return cls(
            user_id=data["userId"],
            user_name=data["userName"],
            is_admin=data["isAdmin"],
            last_login=data["lastLogin"],
            address=Address.from_dict(data["address"]),
            projects=[Project.from_dict(v0) for v0 in data["projects"]],
        )

1 sample · 3 classes

General notes

How it works

Each sample is read as a value of the root class. Classes are written in dependency order, so nested classes come first and every annotation resolves.

dataclasses
Fields without defaults come first, then optional ones with = None. from_dict() maps the original keys to the snake_case attributes and builds nested objects, lists and dicts of them.
Pydantic v2
Renamed attributes get Field(alias="firstName") and the model sets populate_by_name=True, so both spellings validate.
TypedDict
Keys must match the JSON exactly, so names are never changed; keys that are not identifiers use the functional TypedDict("Root", {...}) form, and optional keys are NotRequired.
Syntax
3.11+ writes list[str] and str | None; 3.8+ uses List, Optional and typing_extensions.

Questions

What happens to keys like class or first-name?

Keywords get a trailing underscore (class_), other names are converted to snake_case (first_name), and the original key is kept in an alias or in from_dict(). Names that would shadow str, list or self get an underscore too.

Does Pydantic parse nested objects for me?

Yes. Root.model_validate(data) builds the nested models from plain dicts, using the aliases. With dataclasses, Root.from_dict(json.loads(text)) does the same job.

Is my JSON uploaded?

No. The code is generated by JavaScript running in this tab, and nothing you paste leaves it. The site counts page views with Cloudflare Web Analytics, which sets no cookies and never receives what you paste.