Request Bodies: Handling JSON Payloads

Request Bodies: Handling JSON Payloads

Master POST requests in FastAPI. Learn how to use Pydantic models to receive, validate, and process complex JSON data.

Request Bodies: Handling JSON Payloads

When you want to send data from a browser or app to your API (like creating a new user or saving a document), you don't put that data in the URL. You put it in the Request Body.

In FastAPI, we handle request bodies using Pydantic Models.


1. Defining a Schema

Think of a Pydantic model as a "Blueprint" or a "Contract." It tells FastAPI exactly what fields you expect and what their types are.

from pydantic import BaseModel
from typing import Optional

class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None

2. Receiving the Body

To receive this JSON data in your endpoint, you simply use the model as a type hint for your argument.

@app.post("/items/")
async def create_item(item: Item):
    # 'item' is now a real Python object with attributes!
    item_dict = item.dict()
    if item.tax:
        price_with_tax = item.price + item.tax
        item_dict.update({"total_price": price_with_tax})
    return item_dict

The Magic Behind the Scenes:

When a request hits this endpoint:

  1. FastAPI reads the Request Body as JSON.
  2. It validates the data against the Item model.
  3. If a field is missing or the wrong type, it returns a 422 error.
  4. If valid, it gives you a clean Python object to work with.

3. Nested Structures

AI and Enterprise APIs often need complex, nested data. Pydantic handles this naturally by allowing models to be used as types inside other models.

class Tag(BaseModel):
    id: int
    label: str

class Item(BaseModel):
    name: str
    tags: list[Tag]  # A list of nested objects!

4. The Body Helper

Sometimes you don't want a whole model for just one field. You can use the Body helper to extract a single value from the JSON payload.

from fastapi import Body

@app.post("/update-status")
async def update_status(status: str = Body(...)):
    return {"new_status": status}

Visualizing the Flow

graph LR
    A["Raw JSON Body"] --> B["FastAPI / Pydantic"]
    B -- Validation Fail --> C["422 Unprocessable Entity"]
    B -- Validation Pass --> D["Python Object (Code)"]
    D --> E["Business Logic / Database"]

Summary

  • BaseModel is the starting point for all request bodies.
  • Type Validation is automatic and strict.
  • Nested Models allow for extremely complex data structures.
  • Documentation: Your schemas are automatically used to generate the "Request Body" section in Swagger UI.

In the next lesson, we wrap up Module 4 with Exercises to test your routing and payload skills.


Exercise: The User Signup

Design a Pydantic model for a User Signup. Requirements:

  • username (string, required)
  • email (string, required)
  • password (string, required)
  • bio (string, optional)
  • age (integer, optional)

How would your FastAPI function signature look to receive this data in a POST /signup endpoint?

Subscribe to our newsletter

Get the latest posts delivered right to your inbox.

Subscribe on LinkedIn