Skip to content

Tools

JSON to Python

Paste JSON, get frozen dataclasses with from_dict /to_dict — or Pydantic v2 models with aliases. Dates, optionals and int-vs-float inferred honestly. Runs entirely in your browser.

Style:

Generated code

Beta — the generated code is unit- and compile-tested, but inference from one sample can't be perfect; on rare occasions the output may need a tweak. Spot something wrong?Tell me.

What is this tool?

A free JSON-to-Python converter. Paste a JSON document and it generates typed model classes for the whole tree — by defaultfrozen stdlib dataclasses withfrom_dict and to_dict methods that handle key renaming, date parsing and nested models, orPydantic v2 BaseModels if that's your stack. Everything regenerates live as you type, and every place your sample was too thin to type is named in a warning rather than guessed silently.

Your JSON never leaves the browser. The whole pipeline is client-side; the page works offline once loaded.

How to use it

  • Paste JSON on the left — Python appears on the right as you type.
  • Name the root class; nested classes are named from their keys, singularized inside lists (users: […]User).
  • Pick Dataclasses (stdlib only) or Pydantic v2.
  • 3.10+ syntax emits str | None and list[User]; turn it off for Optional[str] / List[User] on older interpreters.
  • Copy or Download the .py file.

Dataclass, Pydantic or TypedDict?

StyleBest forTrade-off
Dataclasses (default)Zero dependencies; real classes with methods; frozen=True gives you hashable, immutable models.No validation — from_dict maps and converts, it doesn't check types at runtime.
Pydantic v2Data crossing a trust boundary — full validation, coercion, model_validate_json straight from bytes.A dependency, and models are heavier than plain dataclasses.
TypedDict (not emitted)Type hints over raw dicts with zero runtime cost.No methods, no conversion, no renaming of awkward keys — for a paste-and-ship model class it usually disappoints; may come later.

Keys that aren't identifiers — aliases done properly

JSON keys like created-at or 1st-placecan't be Python attribute names. The generated field becomescreated_at, and the mapping survives in code, not in your memory: dataclass from_dict/to_dictread and write the original key, and Pydantic fields getField(alias="created-at") withpopulate_by_name=True so both spellings construct. Reserved words get a trailing underscore (importimport_) — same technique.

Dates and the fromisoformat shim

String fields become datetime only when every sample matches ISO 8601. The dataclass reader parses them with:

datetime.fromisoformat(data["created-at"].replace("Z", "+00:00"))

That .replace looks odd but is deliberate: before Python 3.11, fromisoformat rejects the trailingZ that almost every real API sends. The shim is a no-op on 3.11+ and correct back to 3.7. Pydantic parses ISO strings (including Z) natively, so its models skip the shim.

int, float, and why from_dict coerces

Python's json module parses 5 asint — even in a field your models callfloat. A frozen dataclass would happily hold thatint, and my_price / 2 would quietly do integer-flavored math in other contexts. Fields inferred as float (because any sample showed a decimal) are read asfloat(data["price"]), so the model always holds what its type says. Int fields are left strict — 1.5arriving in one is a bug you want to see.

Nullable vs missing

A key that was null in the sample and a key that wasabsent from one list element both type asX | None — but they serialize differently:to_dict always writes the always-present key (null and all), while the optional one is omitted whenNone, so round-trips reproduce your input. Optional fields are also read with data.get(…) instead ofdata[…] — no KeyError on the responses that omit them.

FAQ

Is it free? Yes — free, no sign-up, no limits.

Is my JSON uploaded anywhere? No — fully client-side, works offline after load; only your last input is kept, in your own browser's local storage.

Why did a field come out Any? The sample never pinned its type down — always None, an empty list, or two samples that disagreed. The warnings panel names the exact path.

Which Python does the output target? With "3.10+ syntax" on: 3.10 and later. Off: 3.8+ (viatyping.Optional/List). Either wayfrom __future__ import annotations keeps forward references painless.

Pydantic v1? Not emitted — v2 has been current since 2023; the v1 API differs enough (Config,parse_obj) that mixing them breaks. The dataclass style works everywhere.

Can it read a JSON Schema? Not yet — v1 infers from samples; schema input is planned.

Built from scratch for this site in vanilla TypeScript — a pure, unit-tested inference engine with golden-tested emitters and zero runtime dependencies.