JSON to Pydantic Generator

JSON Input
1
Root Class
Pydantic v2 Output

Last updated:

Jsonic's JSON to Pydantic generator converts a JSON object into Pydantic v2 BaseModel class definitions. It infers Python types — str, int, float, bool — distinguishes integers from floats, wraps null-able fields in Optional, generates List[T] for arrays, and creates separate nested BaseModel classes for nested objects. Field names are converted to snake_case. The generator outputs ready-to-use Python code including all necessary imports from pydantic and typing. All conversion happens in your browser with no data upload.

From a JSON object to a BaseModel class

A Pydantic model is a subclass of BaseModel whose fields are plain annotated class attributes — no decorators or registration. The generator reads one JSON object and emits one such class, mapping each key to a typed field. This gives you parsing, coercion, and validation for free the moment you call a parse method on the class.

{
  "id": 1,
  "name": "Alice",
  "email": "alice@example.com",
  "is_active": true
}
from pydantic import BaseModel

class Model(BaseModel):
    id: int
    name: str
    email: str
    is_active: bool

How JSON values become Python types

The generator inspects each value and picks a type. Numbers are the subtle case: 42 becomes int while 9.99 becomes float, decided by the presence of a decimal point. JSON has no date or UUID type, so an ISO timestamp arrives as str — promote it to datetime yourself if you want Pydantic to coerce and validate it.

{
  "sku": "WIDGET-1",
  "quantity": 3,
  "unit_price": 9.99,
  "in_stock": true,
  "released_at": "2026-01-01T00:00:00Z"
}
from pydantic import BaseModel

class Model(BaseModel):
    sku: str
    quantity: int            # no decimal -> int
    unit_price: float        # decimal point -> float
    in_stock: bool
    released_at: str         # JSON has no date type; widen to datetime by hand

Optional fields and defaults from null

A null value produces Optional[T] with a default of None. The default matters: Optional[str] alone only means the value may be null — without = None Pydantic still requires the key to be present. For collection defaults, hand-edit to Field(default_factory=list) to dodge the shared-mutable-default trap.

{
  "id": 1,
  "name": "Alice",
  "middle_name": null,
  "tags": []
}
from pydantic import BaseModel, Field
from typing import Optional

class Model(BaseModel):
    id: int
    name: str
    middle_name: Optional[str] = None         # null -> Optional + default
    tags: list[str] = Field(default_factory=list)  # safe mutable default

Nested models and List[Model]

Each nested JSON object becomes its own BaseModel subclass; an array of objects becomes List[ItemModel] plus a class for the element. Nested classes are declared before the models that reference them so Python resolves the names directly. This recurses to any depth.

{
  "order_id": "ORD-001",
  "customer": { "id": 42, "name": "Alice" },
  "items": [
    { "product": "Widget", "quantity": 3 },
    { "product": "Gadget", "quantity": 1 }
  ]
}
from pydantic import BaseModel
from typing import List

class Customer(BaseModel):
    id: int
    name: str

class Item(BaseModel):
    product: str
    quantity: int

class Model(BaseModel):
    order_id: str
    customer: Customer        # nested object -> nested model
    items: List[Item]         # array of objects -> List[Item]

Parse and validate JSON with the generated model

Once you have the class, model_validate_json() parses a raw JSON string into a validated instance in a single step — it runs through pydantic-core's Rust parser, so there is no separate json.loads() call. Use model_validate() when you already hold a Python dict, and TypeAdapter for a top-level array. Any failure raises a single ValidationError that lists every bad field at once.

from pydantic import BaseModel, ValidationError, TypeAdapter

class Model(BaseModel):
    id: int
    name: str

# 1) Raw JSON string -> validated model (preferred)
m = Model.model_validate_json('{"id": 1, "name": "Alice"}')

# 2) Already a Python dict
m2 = Model.model_validate({"id": 2, "name": "Bob"})

# 3) Top-level JSON array
users = TypeAdapter(list[Model]).validate_json('[{"id":1,"name":"A"},{"id":2,"name":"B"}]')

# 4) Structured errors instead of silent bad data
try:
    Model.model_validate_json('{"id": "oops"}')
except ValidationError as e:
    print(e.error_count(), "errors")   # missing name + bad id

Aliases, snake_case keys, and v2 vs v1

camelCase keys are emitted as snake_case to match PEP 8 (userId user_id). To keep accepting the original wire names, add a Field(alias=...) plus populate_by_name=True. On versions: the class bodies are identical across Pydantic v1 and v2 — what changed are the method names. In v2, model_validate_json() replaces parse_raw(), model_dump() replaces dict(), and ConfigDict replaces the inner Config class, all backed by a Rust core that is 5–50× faster.

from pydantic import BaseModel, Field, ConfigDict

class Model(BaseModel):
    model_config = ConfigDict(populate_by_name=True)  # accept both names
    user_id: int = Field(alias="userId")              # camelCase wire name
    first_name: str = Field(alias="firstName")

# accepts the original API payload...
Model.model_validate_json('{"userId": 1, "firstName": "Alice"}')
# ...and the pythonic form
Model(user_id=1, first_name="Alice")

For the deeper walkthrough — ValidationError handling, JSON Schema export, and FastAPI integration — read the JSON to Pydantic guide. If you target a TypeScript codebase instead of Python, use JSON to TypeScript.

How to convert JSON to a Pydantic model

  1. Paste your JSON object into the left panel, or click Example to load a sample.
  2. Optionally change the root class name (default: Model).
  3. Click Generate.
  4. The right panel shows the Pydantic v2 BaseModel class definitions with correct Python types.
  5. Copy the code and paste it into your Python project.

FAQ

What Pydantic version does this generate for?

The generator outputs Pydantic v2 syntax using class Model(BaseModel): with standard field annotations. Pydantic v2 uses the same field annotation style as v1, so the class bodies are compatible with both.

How are types inferred from JSON?

JSON strings → str, integers → int, decimals → float, booleans → bool, null → Optional[T], arrays → List[T], objects → nested BaseModel. Numbers split on the decimal point: 42 is int, 9.99 is float.

How are nullable fields handled?

A null value (or a key present in only some array items) becomes Optional[T] with a default of None, so every item validates against one model.

What happens to camelCase field names?

camelCase keys are converted to snake_case to follow PEP 8. Add Field(alias="userId") with populate_by_name=True if you need to accept both forms.

Can it handle nested objects and arrays of objects?

Yes. Each nested object becomes a separate BaseModel subclass, and an array of objects generates List[ItemModel] plus the item class, declared in dependency order.

How do I parse JSON with the generated model?

Call Model.model_validate_json(json_str) for a raw string or Model.model_validate(dict) for a Python dict. Both raise ValidationError on bad data.

Is my data uploaded?

No. Type inference and code generation run entirely in your browser. Your JSON never leaves your machine.