JSON to Python — Generate Python Dataclass from JSON

Paste any JSON and instantly generate a ready-to-use Python dataclass. Customize the class name, handle nested objects and arrays, and copy the output to your clipboard. 100% client-side — your data stays private.

JSON to Python Converter

Input (JSON)
Output (Python) Ready

            

How do you turn JSON into a Python dataclass? A dataclass mirrors a JSON object as a typed class: each key becomes an annotated attribute and the @dataclass decorator generates __init__, __repr__ and __eq__ from those annotations. This tool parses one sample document and maps JSON's value types onto str, int, float, bool, Optional, List and nested classes, then prints the class together with the import lines it needs.

How to Use the JSON to Python Converter

  1. Paste one representative object — The left panel takes a single JSON object — a real API response is ideal. Press Load Sample to see the shape of the output first. Paste a bare array and the keys become 0, 1, 2, so send in one element of the array instead.
  2. Name the class — The Class name field sets the outer class; it defaults to MyModel. Names of nested classes are derived from their field names, converted from snake_case to PascalCase, so billing_address produces BillingAddress.
  3. Read the generated types as you type — Conversion re-runs on every keystroke. The status tag reads Converted on success and Error with the parser's message when the JSON does not parse, which makes it a quick syntax check as well.
  4. Check the fields the sample could not decide — A field that was null in your sample becomes Optional[Any], an empty array becomes List[Any], and a whole number becomes int even when the API can also return a decimal. Those are the annotations worth correcting by hand.
  5. Copy the code and rearrange the nested classesCopy puts the whole listing on the clipboard. Nested dataclasses are emitted inside the class that uses them, so move each one above the class that references it before running the file.

How the Type Mapping Works

The document is parsed with the browser's JSON parser, which leaves six kinds of value to translate: string, number, boolean, null, object and array. Python's dataclasses module needs one annotated attribute per key, so the conversion is a direct walk over the parsed structure. Everything is inferred from the single sample you paste — there is no schema involved, so the output describes that document rather than the endpoint that produced it.

JSON valueGenerated annotationNote
"Alice"strDates, UUIDs and enums all arrive as strings and stay str
30intAny number with no fractional part, so 30.0 also becomes int
95.5floatOnly numbers that carry a fraction in the sample
trueboolStrings such as "true" are not treated as booleans
nullOptional[Any] = NoneThe sample gives no clue about the real type behind a null
{ … }A nested @dataclassNamed from the field, snake_case converted to PascalCase
[]List[Any]An empty array carries no element type
["a", "b"]List[str]Taken from the first element only
[{ … }]List[ClassName]The first element becomes a nested dataclass

Two consequences of inferring from one sample are worth planning for. Because only the first array element is inspected, a heterogeneous list — a mix of objects and strings, or objects with different key sets — is typed from whichever value happened to come first. And because integers and floats are told apart by whether the sampled value has a fractional part, a price that reads 20 today and 19.99 tomorrow is annotated int. Widen those to float, or to a union, by hand.

Field names are sanitised by replacing every character that is not a letter, digit or underscore with an underscore, so "user-id" becomes user_id and "@type" becomes _type. That covers hyphens and punctuation but not two other collisions: a key that is a Python keyword, such as class, from or import, and a key that starts with a digit. Both produce a syntax error and need renaming, usually alongside an alias in whatever loads the data.

Before the Generated Code Runs

The output is a scaffold rather than a finished module. Three things routinely need a moment of editing, and all three fail loudly the first time you import the file rather than quietly at runtime.

  • Nested classes are defined after they are used. Each inner dataclass is written inside the body of the class that references it, below the field list. Python evaluates the annotation before it reaches the definition, so importing the file raises a NameError. Cut each nested class out, dedent it, and paste it above the class that uses it — the annotations then resolve in order.
  • Fields with defaults must come last. Only null fields get a default (= None). If one of those appears before a field without a default, the dataclass decorator raises TypeError: non-default argument follows default argument. Move the optional fields to the bottom of the class, or give every field a default.
  • Imports are unconditional. Optional, List and Any are always imported even when the document uses none of them. Harmless at runtime, but linters will flag the unused names, so trim the import line to what you keep.

None of these are hard fixes; they are the difference between a generator that guesses your intent and one that shows its work. Once the classes are in the right order the file is plain standard-library Python with no third-party dependency, which is exactly why dataclasses is a good target for generated code.

Turning the Class Into Actual Objects

A dataclass describes a shape; it does not parse anything. @dataclass writes the constructor, the __repr__ and the equality comparison from your annotations, and it deliberately does not validate types at runtime — annotate a field int and pass a string and Python will accept it. Type checkers such as mypy or Pyright are what turn those annotations into real feedback.

data = json.loads(payload); model = MyModel(**data)

That one-liner works for a flat document. As soon as there are nested objects it stops being enough: the nested keys stay as plain dictionaries, so model.address is a dict rather than an Address, and attribute access on it fails. For anything nested you either construct the inner classes explicitly, write a from_dict classmethod, or reach for a library that builds typed objects from dictionaries — pydantic is the usual choice when validation matters, and its models look close enough to these dataclasses that the generated field list transfers with little editing.

Going the other way is simpler: dataclasses.asdict(model) converts an instance, including nested dataclasses, back into dictionaries ready for json.dumps. That round trip is the main practical reason to type a payload at all — you get autocompletion and a checkable contract on the way in, and a clean serialisation on the way out.

Frequently Asked Questions

Yes. An object-valued field becomes its own dataclass, named after the field with snake_case converted to PascalCase — an address key produces an Address class. The nested classes are written inside the body of the class that uses them, below the field list, so move each one above its parent before importing the file. Nesting goes as deep as your document does.

The dataclasses module is part of the standard library from Python 3.7 onwards, and Optional, List and Any come from typing, which is older still. Nothing in the output needs a third-party package. On 3.9 and later you can replace List[str] with the built-in list[str], and on 3.10 and later Optional[X] with X | None, if you prefer the modern spelling.

A field that is null in your sample is annotated Optional[Any] = None, because a null tells you the field is nullable but nothing about the type behind it. Replace Any with the real type once you know it. Watch the ordering too: a field with a default cannot precede one without, so a nullable field near the top of the class will make the decorator raise a TypeError until you move it down.

Because the sample decided it. Numbers are classified by whether the parsed value has a fractional part, so 19.99 gives float while 20 and even 20.0 give int — JSON does not distinguish the two and the parser hands back one numeric type. For money, ratios, coordinates and anything else that can be fractional, widen the annotation yourself; the generator has no way to know.

Paste a single element instead. A top-level array has numeric keys, so the generator would produce fields named 0, 1 and 2, which are not valid Python identifiers. Take one representative object out of the array, generate the class for it, and annotate the collection as List[MyModel] where you use it. Arrays inside the document are handled normally.

No. Parsing and code generation both run in JavaScript in your tab, so a production payload never leaves the machine and the page works offline once loaded. Be aware that the input and class name are written into the page URL so the session survives a reload — that rewrite is local, but the JSON is visible in the address bar, so clear the panel before sharing the link.

Use a dataclass when the data is already trusted and you want a typed container with no dependencies: it is standard library, fast to construct, and mypy or Pyright will check the annotations statically. Reach for pydantic when the JSON comes from outside your system and you want the types enforced and coerced at runtime, with real error messages for bad input. The field list generated here transfers to either with little editing.

Almost always because a nested class is referenced before it is defined. The generator writes the field list first and the inner dataclasses after it, but Python evaluates a class-body annotation as it reads it. Move each nested class above the class that references it and dedent it to module level — or, as a quick fix, add from __future__ import annotations at the top, which defers annotation evaluation.

Use Cases

API Response Models

Generate typed models from REST API responses for robust data handling in Python clients.

Config File Parsing

Convert JSON configuration files into strongly-typed Python classes for validated access.

Rapid Prototyping

Skip boilerplate — paste a sample JSON and get a working dataclass in seconds.

Documentation & Testing

Generate sample dataclasses to document expected JSON structures for your team.