FastAPI Pydantic Model

Pydantic is a core dependency of FastAPI, used for data validation and serialization. It lets you define data models using standard Python type annotations, automatically handling data validation, type conversion, and documentation generation.


What is Pydantic

Pydantic is a Python data validation library. Its core philosophy is:Define data structures with Python type annotations, and Pydantic automatically handles validation and conversionIn FastAPI, Pydantic is mainly used for:

PurposeDescription
Request body validationAutomatically validate whether JSON data sent by clients conforms to the model definition
Response body serializationAutomatically convert model data into JSON responses
Automatic documentationModel fields, types, and validation rules automatically appear in the API documentation
Editor supportModel attributes get full autocompletion in the editor

Define Pydantic models

Create an inheritanceBaseModelclasses that declare fields using standard Python types:

Example

from pydantic import BaseModel


class Item(BaseModel):
    name: str               # Required: Product name
    description: str | None = None  # Optional: Product description
    price: float            # Required: Product price
    tax: float | None = None        # Optional: tax

Whether a field is required depends on whether it has a default value:

FieldsDeclaration methodRequired?
namename: strRequired
descriptiondescription: str | None = NoneOptional
priceprice: floatRequired
taxtax: float | None = NoneOptional

Use Pydantic models

As request body

The most common usage is declaring a model as a parameter of a path operation function:

Example

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None


@app.post("/items/")
async def create_item(item: Item):
    # FastAPI automatically validates the request body and, after validation passes, assigns it to the item parameter
    return item

Access and manipulate model data

Example

@app.post("/items/")
async def create_item(item: Item):
    # Access model attributes
    print(item.name)       # Directly access attributes
    print(item.price)      # Editor provides auto-completion

    # Serialize to dictionary
    item_dict = item.model_dump()
    print(item_dict)       # {"name": "Foo", "description": None, "price": 45.2, "tax": None}

    # Serialize to JSON string
    item_json = item.model_dump_json()
    print(item_json)       # '{"name":"Foo","description":null,"price":45.2,"tax":null}'

    return item_dict

Pydantic v2 Usagemodel_dump()andmodel_dump_json()Replaces v1'sdict()andjson()method. The new method has better performance (implemented in Rust under the hood).


Model validation example

When data sent by a client does not conform to the model definition, FastAPI returns detailed validation errors:

Example

# The client sent data missing required fields
POST /items/
{
    "description": "missing name and price"
}

# FastAPI Response Validation Error
{
    "detail": [
        {
            "type": "missing",
            "loc": ["body", "name"],
            "msg": "Field required",
            "input": {"description": "missing name and price"}
        },
        {
            "type": "missing",
            "loc": ["body", "price"],
            "msg": "Field required",
            "input": {"description": "missing name and price"}
        }
    ]
}

If incorrectly typed data is sent:

// price 应该是数字,但传了字符串
{
    "name": "Foo",
    "price": "not a number"
}

// FastAPI 返回的错误
{
    "detail": [
        {
            "type": "float_parsing",
            "loc": ["body", "price"],
            "msg": "Input should be a valid number, unable to parse string as a number",
            "input": "not a number"
        }
    ]
}

Common Pydantic v2 methods

Methodsv2 (Recommended)v1 (deprecated)Description
Serialize to dictionaryitem.model_dump()item.dict()Convert a model into a Python dictionary
Serialize to JSONitem.model_dump_json()item.json()Convert model to JSON string
Create from dictionaryItem.model_validate(data)Item.parse_obj(data)Create and validate a model from a dictionary
Create from JSONItem.model_validate_json(json_str)Item.parse_raw(json_str)Create a model from a JSON string
Get JSON SchemaItem.model_json_schema()Item.schema()Obtaining the model's JSON Schema

Model configuration (model_config)

Pydantic v2 Usagemodel_configReplaces v1'sConfigInner class:

Example

from pydantic import BaseModel, ConfigDict


class Item(BaseModel):
    name: str
    price: float

    # Pydantic v2 configuration method
    model_config = ConfigDict(
        json_schema_extra={  # Display examples in the API documentation
            "examples": [
                {
                    "name": "Foo",
                    "price": 35.4
                }
            ]
        }
    )

In Pydantic v2,orm_mode = Truechanged tofrom_attributes = True,schema_extrachanged tojson_schema_extra,allow_population_by_field_namechanged topopulate_by_name。


Model inheritance

Pydantic models support inheritance, making it easy to create input models and output models:

Example

from pydantic import BaseModel, EmailStr


# Base Model
class UserBase(BaseModel):
    username: str       # Required
    email: EmailStr     # Required, automatically validates email format
    full_name: str | None = None  # Optional


# Input model for creating a user (including password)
class UserCreate(UserBase):
    password: str       # Required


# Output model for returning user information (does not include password)
class UserOut(UserBase):
    id: int             # Generated by the server


# Usage example
@app.post("/users/", response_model=UserOut)
async def create_user(user: UserCreate):
    # Function receives UserCreate (with password), but response uses UserOut (without password)
    # This way the password will not appear in the API response.
    return {"id": 1, **user.model_dump(exclude={"password"})}

Using different input and output models is an important means of protecting sensitive data. Never return sensitive fields such as passwords in API responses.


Summary

Key points of Pydantic models:

  • UsageBaseModelDefine data models with standard Python types declaring fields
  • Fields with default values are optional, fields without default values are required
  • v2 usagemodel_dump()、model_validate()and other new methods
  • Create different input/output models through model inheritance to protect sensitive data
  • All validation and documentation are automatic—just declare types once
other extensions