Головне, що треба знати про формати відповідей API і JSON: якщо твій API не повертає дані у форматі JSON — це привід насторожитися.
Майже всі сучасні API використовують саме JSON — він легкий, зручний, читабельний для людини і підтримується практично всіма мовами програмування.
FastAPI з коробки працює з JSON, тож нам майже не доведеться докладати зусиль для налаштування цього процесу.
Давай створимо невеликий приклад. Спочатку налаштуємо ендпоінт, який повертає просту відповідь:
from fastapi import FastAPI
app = FastAPI()
@app.get("/hello")
async def say_hello():
return {"message": "Hello, FastAPI!"}
Якщо запустиш застосунок через Uvicorn (uvicorn main:app --reload), перейди на http://127.0.0.1:8000/hello і побачиш результат — FastAPI автоматично поверне JSON:
{
"message": "Hello, FastAPI!"
}
FastAPI автоматично конвертує Python-об'єкти (словники, списки) в JSON. Все, що треба робити — просто повертати дані з обробника (функції) ендпоінта.
Структура JSON-відповідей
JSON-відповіді — це структуровані дані у вигляді об'єктів, масивів, рядків і чисел. Ось приклад більш складної відповіді:
@app.get("/user")
async def get_user():
return {
"id": 1,
"name": "John Doe",
"email": "johndoe@example.com",
"active": True,
"roles": ["admin", "editor"]
}
Тут повертається складний об'єкт зі вкладеними структурами даних: рядками, булевими значеннями і списками.
Результат запиту:
{
"id": 1,
"name": "John Doe",
"email": "johndoe@example.com",
"active": true,
"roles": ["admin", "editor"]
}
Налаштування обробки відповідей
FastAPI дозволяє налаштовувати відповіді для складніших випадків, наприклад, якщо потрібно повернути об'єкт певного типу, змінити заголовки або статус відповіді.
Повертані типи
FastAPI підтримує анотацію типів, що робить наш код читабельнішим і зрозумілішим. У простих випадках можна використовувати Python-словники, списки або рядки.
from typing import Dict
@app.get("/product", response_model=Dict[str, str])
async def get_product():
return {"name": "Laptop", "brand": "FastAPI"}
FastAPI перевірить, що повернутий об'єкт відповідає вказаній структурі. Якщо ні — кинеться помилка.
Встановлення HTTP-статусів
Іноді треба повернути не лише дані, а й особливий HTTP-статус. Наприклад, 201 Created для успішного створення ресурсу. Це можна зробити за допомогою класу JSONResponse:
from fastapi.responses import JSONResponse
@app.post("/item")
async def create_item():
return JSONResponse(status_code=201, content={"message": "Item created"})
Тепер, викликаючи цей ендпоінт, ти отримаєш:
{
"message": "Item created"
}
з HTTP-статусом 201.
Встановлення заголовків відповіді
Заголовки headers використовуються для передачі додаткових даних про запит або відповідь. Наприклад, можна вказати тип контенту відповіді:
from fastapi.responses import JSONResponse
@app.get("/custom-header")
async def custom_header():
return JSONResponse(
content={"message": "Custom Header!"},
headers={"X-Custom-Header": "Awesome FastAPI"}
)
Результат запиту:
HTTP/1.1 200 OK
Content-Type: application/json
X-Custom-Header: Awesome FastAPI
{
"message": "Custom Header!"
}
Використання response_model для суворої типізації
FastAPI пропонує потужний інструмент для опису структури повертаного JSON — response_model. Він допомагає гарантувати, що відповідь завжди слідує заданій схемі.
Приклад з використанням Pydantic
Створимо Pydantic-модель для опису структури відповіді:
from pydantic import BaseModel
class User(BaseModel):
id: int
name: str
email: str
active: bool
roles: list[str]
@app.get("/user", response_model=User)
async def get_user():
return {
"id": 1,
"name": "John Doe",
"email": "johndoe@example.com",
"active": True,
"roles": ["admin", "editor"]
}
response_model дозволяє FastAPI автоматично перевірити відповідність відповіді моделі User. Якщо повернеться об'єкт, що не відповідає моделі, ти отримаєш помилку.
Обробка необов'язкових полів
Не всі дані в JSON мають бути заповнені. FastAPI і Pydantic дозволяють описувати опціональні поля.
from typing import Optional
class Product(BaseModel):
name: str
description: Optional[str] = None # Поле може бути порожнім
@app.get("/product", response_model=Product)
async def get_product():
return {"name": "Laptop"} # "description" не передається
Результат запиту:
{
"name": "Laptop",
"description": null
}
Кастомізація форматів відповіді
Іноді JSON — це круто, але хочеться більшого. Наприклад, повернути CSV або XML. FastAPI дозволяє кастомізувати формат відповіді за допомогою Response.
Наведемо приклад з текстовою відповіддю
from fastapi.responses import Response
@app.get("/text")
async def get_text():
return Response(content="Hello, this is plain text!", media_type="text/plain")
Результат:
Hello, this is plain text!
А тепер — приклад з кастомним форматом:
@app.get("/custom-response")
async def custom_response():
custom_json = '<custom><message>Hello, XML!</message></custom>'
return Response(content=custom_json, media_type="application/xml")
Це корисно, якщо твій клієнт очікує дані у нестандартному форматі.
Приклади складних відповідей
Повернення списків об'єктів
Якщо твій API має повернути кілька об'єктів, просто поверни список словників або Pydantic-моделей:
class Item(BaseModel):
id: int
name: str
price: float
@app.get("/items", response_model=list[Item])
async def get_items():
return [
{"id": 1, "name": "Laptop", "price": 999.99},
{"id": 2, "name": "Phone", "price": 699.99}
]
Результат:
[
{"id": 1, "name": "Laptop", "price": 999.99},
{"id": 2, "name": "Phone", "price": 699.99}
]
Обробка помилок у відповідях
FastAPI дозволяє легко формувати відповіді про помилки. Можеш використовувати HTTPException для повернення кастомних повідомлень:
from fastapi import HTTPException
@app.get("/error")
async def error():
raise HTTPException(status_code=404, detail="Item not found")
Відповідь:
{
"detail": "Item not found"
}
Тепер ти знаєш, як працювати з відповідями в FastAPI, максимально використовувати JSON, налаштовувати заголовки і навіть повертати користувацькі формати. Далі нас чекає вбудована документація в FastAPI — це те, що змушує розробників ще більше любити цей фреймворк.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ