Files
python-doc/Docs/Libs/FastAPI/09-Responces.md
2026-05-13 17:00:43 +03:30

8.1 KiB
Raw Blame History

FastAPI Response Model and JSONResponse

Overview

This document explains two important FastAPI response concepts:

  1. Using response_model to control what data is returned to the client
  2. Using JSONResponse when you need explicit control over the response body, status code, or headers

Response models are especially useful when you want to hide sensitive fields such as passwords from API responses.


1. Response Model

Incorrect Example

The following code has several issues:

from fastapi import FastAPI, status , HTTPExption
from pydantic import BaseModel

app = FastAPI()


class usersin(BaseModel):
    username: str
    pass: str 

class usersout(BaseModel):
    username: str


@app.post("/user")
def home(user: usersin, responce_model=usersout):
    return user

Problems in the Code

1. HTTPExption is misspelled

Correct import:

HTTPException

2. pass cannot be used as a field name

pass is a reserved keyword in Python.

Instead of:

pass: str

Use:

password: str

3. response_model is written in the wrong place

This is incorrect:

def home(user: usersin, responce_model=usersout):

response_model must be passed inside the route decorator.

Correct:

@app.post("/user", response_model=UserOut)

4. responce_model is misspelled

Correct spelling:

response_model

2. Correct Response Model Example

Create or update main.py with the following content:

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


class UserIn(BaseModel):
    username: str
    password: str


class UserOut(BaseModel):
    username: str


@app.post("/user", response_model=UserOut)
def create_user(user: UserIn):
    return user

3. How Response Model Works

Input Model

class UserIn(BaseModel):
    username: str
    password: str

This model defines the data that the API receives from the client.

Example request body:

{
  "username": "abbas",
  "password": "123456"
}

The API accepts both fields:

username
password

Output Model

class UserOut(BaseModel):
    username: str

This model defines the data that the API returns to the client.

Even though the endpoint receives the password, the response only returns the username.

Example response:

{
  "username": "abbas"
}

The password is removed from the response automatically.


4. Endpoint Definition

@app.post("/user", response_model=UserOut)
def create_user(user: UserIn):
    return user

This creates a POST endpoint at:

POST /user

The endpoint receives data based on UserIn and returns data based on UserOut.

FastAPI uses response_model to filter the response before sending it to the client.


5. Example Request

Using curl

curl -X POST "http://localhost:8000/user" \
  -H "Content-Type: application/json" \
  -d '{"username": "abbas", "password": "123456"}'

Response

{
  "username": "abbas"
}

The password is not included in the response.


6. Why Use Response Models

Response models are useful because they help you:

Protect sensitive data Keep API responses consistent Control exactly what the client receives Improve automatic documentation Validate response data before sending it Separate input schemas from output schemas


7. Better Version with Status Code

For user creation endpoints, it is better to return 201 Created.

from fastapi import FastAPI, status
from pydantic import BaseModel

app = FastAPI()


class UserIn(BaseModel):
    username: str
    password: str


class UserOut(BaseModel):
    username: str


@app.post(
    "/user",
    response_model=UserOut,
    status_code=status.HTTP_201_CREATED
)
def create_user(user: UserIn):
    return user

8. JSONResponse

FastAPI automatically converts Python dictionaries into JSON responses.

For most endpoints, this is enough:

@app.get("/")
def home():
    return {"msg": "API is working"}

However, FastAPI also allows you to use JSONResponse when you need more control.


9. Example Application Using JSONResponse

Create or update main.py with the following content:

from fastapi import FastAPI, status
from fastapi.responses import JSONResponse

app = FastAPI()


@app.get("/")
def home():
    return JSONResponse(
        content={"msg": "API is working"},
        status_code=status.HTTP_200_OK
    )

10. Response Behavior

Endpoint

GET /

Response Body

{
  "msg": "API is working"
}

HTTP Status Code

200 OK

11. Default Response vs JSONResponse

Default FastAPI Response

@app.get("/")
def home():
    return {"msg": "API is working"}

This is the recommended style for most simple APIs.

FastAPI automatically serializes the dictionary into JSON.


Explicit JSONResponse

return JSONResponse(
    content={"msg": "API is working"},
    status_code=status.HTTP_200_OK
)

This gives more direct control over the response.


12. When to Use JSONResponse

Use JSONResponse when you need to:

Return dynamic status codes Add custom headers Customize the response structure manually Return responses from exception handlers Return responses from middleware Override FastAPIs default response behavior


13. Example: JSONResponse with Custom Status Code

from fastapi import FastAPI, status
from fastapi.responses import JSONResponse

app = FastAPI()


@app.post("/login")
def login():
    return JSONResponse(
        content={"msg": "Login successful"},
        status_code=status.HTTP_200_OK
    )

14. Example: JSONResponse with Headers

from fastapi import FastAPI
from fastapi.responses import JSONResponse

app = FastAPI()


@app.get("/custom")
def custom_response():
    return JSONResponse(
        content={"msg": "Custom response"},
        headers={"X-App-Version": "1.0.0"}
    )

15. Complete Example with Response Model and JSONResponse

from fastapi import FastAPI, status
from fastapi.responses import JSONResponse
from pydantic import BaseModel

app = FastAPI()


class UserIn(BaseModel):
    username: str
    password: str


class UserOut(BaseModel):
    username: str


@app.get("/")
def home():
    return JSONResponse(
        content={"msg": "API is working"},
        status_code=status.HTTP_200_OK
    )


@app.post(
    "/user",
    response_model=UserOut,
    status_code=status.HTTP_201_CREATED
)
def create_user(user: UserIn):
    return user

16. Running the Application

Start the FastAPI application using uvicorn:

uvicorn main:app --reload

The API will run at:

http://localhost:8000

Interactive API documentation will be available at:

http://localhost:8000/docs

17. Best Practices

Use response_model to control API output.

Never return sensitive data such as passwords, tokens, or secrets.

Use separate models for input and output.

Use clear class names such as UserIn and UserOut.

Use password instead of pass because pass is a reserved Python keyword.

Place response_model inside the route decorator, not inside the function parameters.

Prefer returning normal dictionaries for simple responses.

Use JSONResponse only when extra control is required.

Use proper HTTP status codes, such as:

200 OK
201 Created
400 Bad Request
401 Unauthorized
404 Not Found
500 Internal Server Error

Do not use uvicorn --reload in production.


18. DevOps Production Note

In production, the FastAPI application should usually run behind a production-grade ASGI server setup and a reverse proxy.

A common production stack is:

FastAPI
Gunicorn with Uvicorn workers
Nginx or Traefik
Docker or Kubernetes
PostgreSQL or another persistent database

The development command:

uvicorn main:app --reload

is only for local development.

For production, use a more stable process configuration, such as Gunicorn with Uvicorn workers, container health checks, logging, monitoring, and proper secret management.