Home/Learn/Python A–Z/Pydantic — Data Validation from Type Hints

Pydantic — Data Validation from Type Hints

Intermediate
Important Libraries

Pydantic models validate and convert external data using type annotations — the engine behind FastAPI request validation, with field constraints, custom validators, and clean JSON round-trips.

Overview

Data from outside — API bodies, form input, env vars, files — is untrusted. Pydantic turns a type-annotated class into a validating parser: wrong types are coerced when sensible ("42" → 42) or rejected with precise, field-level error messages. Version 2 is Rust-fast. This is THE library to know before FastAPI, because every FastAPI request/response model IS a Pydantic model — learn it here and the framework becomes obvious.

Models, Coercion & Errors

Declare fields with types; instantiate with untrusted data; Pydantic validates, converts, and raises ValidationError listing EVERY problem (not just the first).

Validate + convert + report all errors at once
from pydantic import BaseModel, EmailStr, Field, ValidationError

class SignupRequest(BaseModel):
    name: str = Field(min_length=2, max_length=50)
    email: EmailStr
    age: int = Field(ge=16, le=100)
    skills: list[str] = []
    referral: str | None = None            # optional

ok = SignupRequest(
    name="Asha", email="asha@x.com",
    age="21",                              # str -> int, coerced!
    skills=["python"],
)
print(ok.age, type(ok.age))                # 21 <class 'int'>
print(ok.model_dump())                     # dict
print(ok.model_dump_json())                # JSON string

try:
    SignupRequest(name="A", email="not-an-email", age=12)
except ValidationError as e:
    for err in e.errors():
        print(err["loc"], err["msg"])
# ('name',)  String should have at least 2 characters
# ('email',) value is not a valid email address
# ('age',)   Input should be greater than or equal to 16

Custom Validators & Nested Models

field_validator adds per-field rules; model_validator checks cross-field logic. Models nest naturally — a JSON tree validates in one call.

Field + cross-field rules; nested JSON validation
from pydantic import BaseModel, field_validator, model_validator

class Address(BaseModel):
    city: str
    pincode: str

    @field_validator("pincode")
    @classmethod
    def valid_pin(cls, v):
        if len(v) != 6 or not v.isdigit():
            raise ValueError("pincode must be 6 digits")
        return v

class Student(BaseModel):
    name: str
    cgpa: float
    backlogs: int = 0
    address: Address                       # nested model!

    @model_validator(mode="after")
    def placement_rule(self):
        if self.cgpa < 6.0 and self.backlogs > 2:
            raise ValueError("not eligible: low cgpa AND backlogs")
        return self

raw = {                                    # e.g. json from an API
    "name": "Ravi", "cgpa": 8.2,
    "address": {"city": "Pune", "pincode": "411001"},
}
s = Student(**raw)                         # whole tree validated
print(s.address.city)                      # Pune

# settings from environment — pydantic-settings package:
# class Settings(BaseSettings): db_url: str; debug: bool = False

Key Points to Remember

  • 1Type hints become runtime validation; sensible coercion ("42" → 42), precise errors
  • 2Field(ge=, le=, min_length=...) for constraints; EmailStr and friends for formats
  • 3field_validator for one field, model_validator for cross-field rules
  • 4model_dump()/model_dump_json() serialize; nested models validate whole JSON trees

Interview Questions

Sign in to ask Aria
1

What does Pydantic add over dataclasses? When is each appropriate?

MediumCRED
2

How does FastAPI use Pydantic models under the hood?

MediumMeesho
3

Implement a cross-field validation rule (e.g. end_date after start_date).

MediumAtlassian

Ask Aria about Pydantic — Data Validation from Type Hints

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…