Runtime data validation and settings management powered by type annotations
Pydantic is the de-facto standard for data validation in Python. FastAPI, one of the most popular web frameworks, is built on it. It powers settings management (via pydantic-settings), API request/response schemas, and configuration objects in data pipelines and ML systems.
In production code, Pydantic signals that you write robust, self-documenting data contracts rather than raw dicts. It turns type annotations from passive documentation into active enforcement — coercing and validating data at the boundary between your code and the outside world.
Think of a Pydantic model as a dataclass that actually enforces its types. When you create an instance, Pydantic reads the annotations, coerces compatible inputs (e.g. "42" → 42 for an int field), and raises a detailed ValidationError if anything is wrong — before the bad data reaches your business logic.
A Pydantic model is a class with type-annotated fields. On instantiation, Pydantic validates and coerces input — invalid data raises a detailed ValidationError before any business logic runs.
Fields are defined with standard Python type annotations. Pydantic validates on construction — you cannot create an instance with invalid data, unlike a plain dataclass.
Field() adds constraints beyond the type — minimum length, numeric bounds, regex patterns. It also carries metadata like descriptions that power auto-generated API docs.
Field() adds constraints (gt, ge, lt, le, min_length, max_length, pattern) and metadata like description and alias for JSON key mapping.
Models can reference other models as fields. Pydantic automatically coerces a plain dict into the nested model type — ideal for parsing nested JSON API payloads with no manual instantiation.
You can nest models freely. Passing a plain dict where a nested model is expected triggers automatic coercion — no manual instantiation needed. This makes Pydantic ideal for parsing JSON API payloads.
When type constraints aren't enough, validators let you transform or reject values with custom logic. Field validators run per field; model validators run after all fields are set, enabling cross-field checks.
field_validator runs on a single field and can transform or reject the value. model_validator(mode="after") runs after all fields are set, giving access to the full model for cross-field checks.
ConfigDict sets model-wide behaviour — how strictly types are enforced, how JSON keys map to Python field names, and automatic string cleanup.
strict=True disables coercion — a string won't silently become an int. alias maps a Python field name to a different JSON key. str_strip_whitespace trims incoming strings automatically before validation runs.
Pydantic models need to convert back out — to dicts for ORMs, to JSON strings for APIs. Both methods handle nested models, datetimes, and enums automatically.
model_dump() returns a Python dict; model_dump_json() returns a JSON string. Both handle nested models, datetimes, enums, and custom types out of the box.