Отдать JSON из FastAPI и проверить в браузере без боли
Три способа вернуть JSON из FastAPI-эндпоинта, разница между dict, JSONResponse и ORJSONResponse, и как проверить результат прямо в браузере через встроенный Swagger — за пятнадцать минут от пустого файла до работающего API.

Что понадобится до старта
Прежде чем писать первый эндпоинт, убедитесь, что у вас есть:
- Python 3.10 или новее (проверьте командой
python --version); - установленный пакетный менеджер pip;
- терминал и любой текстовый редактор — VS Code, PyCharm, даже nano подойдёт;
- браузер — Chrome, Firefox или Edge, без расширений для API не обойтись не придётся.
Всё ниже написано для FastAPI 0.115.x и Uvicorn 0.34.x. Если у вас другие мажорные версии, сверьтесь с официальной документацией — поведение отдельных параметров могло измениться.
Шаг 1. Установка FastAPI и Uvicorn
Откройте терминал и выполните:
pip install "fastapi[standard]"
Мета-пакет fastapi[standard] подтянет сам FastAPI, Uvicorn и библиотеки для автоматической документации. После установки выполните:
python -c "import fastapi; print(fastapi.__version__)"
Должна появиться версия вида 0.115.x. Если команда завершилась ошибкой — пакет не встал, проверьте виртуальное окружение.
Шаг 2. Минимальный эндпоинт, который возвращает dict
Создайте файл main.py:
from fastapi import FastAPI
app = FastAPI()
@app.get("/status")
async def get_status():
# FastAPI сам сериализует dict в JSON и выставит Content-Type
return {"alive": True, "version": "0.1.0"}
Запустите сервер:
uvicorn main:app --reload --port 8000
В терминале появится строка Uvicorn running on http://127.0.0.1:8000. Откройте этот адрес с путём /status в браузере — вы увидите чистый JSON:
{"alive":true,"version":"0.1.0"}
Проверка пройдена: если браузер показал JSON, а не ошибку 404 или 500, эндпоинт работает. Флаг --reload перезапускает сервер при каждом сохранении файла — удобно на этапе разработки, но в продакшене его включать не нужно.
Шаг 3. Проверка через встроенный Swagger UI
FastAPI генерирует интерактивную документацию автоматически. Перейдите в браузере по адресу:
http://127.0.0.1:8000/docs
- Найдите карточку
GET /statusи разверните её. - Нажмите Try it out, затем Execute.
- В секции Response body появится JSON-ответ, а рядом — HTTP-код и заголовки.
Никаких Postman и curl на этом этапе не нужно. Swagger позволяет передавать query-параметры, тела запросов и заголовки — всё из браузера.
Альтернативный интерфейс доступен по адресу /redoc — он удобнее для чтения, но не позволяет отправлять запросы.
Шаг 4. Три способа отдать JSON — и когда какой нужен
FastAPI предлагает несколько вариантов формирования JSON-ответа. Разница — в контроле над заголовками, кодами и скорости сериализации.
Вариант A: вернуть dict или Pydantic-модель
Самый короткий путь. FastAPI сериализует объект стандартным json.dumps и выставит Content-Type: application/json и код 200. Подходит для большинства CRUD-эндпоинтов.
from pydantic import BaseModel
class Item(BaseModel):
name: str
price: float
@app.get("/item")
async def get_item() -> Item:
return Item(name="Кабель USB-C", price=490.0)
Аннотация -> Item не только помогает IDE — FastAPI использует её для генерации JSON Schema в Swagger.
Вариант B: JSONResponse — когда нужен другой код или заголовки
from fastapi.responses import JSONResponse
@app.get("/item/{item_id}")
async def get_item_by_id(item_id: int):
if item_id != 42:
return JSONResponse(
status_code=404,
content={"detail": "Товар не найден"},
)
return JSONResponse(
content={"id": 42, "name": "Кабель USB-C"},
headers={"X-Custom-Header": "some-value"},
)
JSONResponse принимает уже готовый словарь и сериализует его сам. Вы напрямую управляете статус-кодом и заголовками — dict-вариант этого не даёт.
Вариант C: ORJSONResponse — когда сериализация тормозит
Библиотека orjson сериализует в несколько раз быстрее стандартного json. Установите её отдельно:
pip install orjson
Затем подключите:
from fastapi.responses import ORJSONResponse
@app.get("/big-list", response_class=ORJSONResponse)
async def get_big_list():
# Представьте, что данные приходят из БД
data = [{"id": i, "value": i * 0.1} for i in range(10_000)]
return ORJSONResponse(content=data)
Разница в скорости заметна на ответах от десятков килобайт и выше. Для маленьких словарей выигрыш теряется на фоне сетевых задержек.
Сравнение вариантов
| Критерий | dict / Pydantic | JSONResponse | ORJSONResponse |
|---|---|---|---|
| Код ответа по умолчанию | 200 | задаёте сами | задаёте сами |
| Кастомные заголовки | нет | да | да |
| Автогенерация схемы в Swagger | да (с аннотацией) | нет | нет |
| Скорость сериализации | стандартная | стандартная | высокая |
| Дополнительная зависимость | нет | нет | orjson |
Если ваш эндпоинт просто возвращает данные и вам не нужен кастомный код ответа — возвращайте Pydantic-модель. Swagger-документация генерируется автоматически, а типизация ловит ошибки ещё до запуска. JSONResponse и ORJSONResponse — для случаев, когда вам действительно нужен контроль над ответом.
Шаг 5. Частая ловушка: datetime и Decimal
Стандартный json.dumps не умеет сериализовать datetime и Decimal. Если вы возвращаете dict с такими полями напрямую, FastAPI выбросит ошибку. Два выхода:
- Используйте Pydantic-модель — она конвертирует
datetimeв ISO-строку иDecimalв число автоматически. - Если возвращаете dict — приведите типы вручную до возврата:
str(my_decimal),my_dt.isoformat().
ORJSONResponse обрабатывает datetime из коробки, но с Decimal поведение зависит от версии orjson — уточняйте в документации пакета.
Сноска. Pydantic — библиотека валидации данных, которую FastAPI использует для описания схем запросов и ответов. Модель Pydantic — это Python-класс, наследующий BaseModel, где каждое поле имеет аннотацию типа. FastAPI сериализует такую модель в JSON и генерирует по ней OpenAPI-схему.
Если не получилось
Пять ошибок, которые встречаются чаще всего при первом запуске:
ModuleNotFoundError: No module named 'fastapi'— пакет не установлен в активном виртуальном окружении. Проверьтеwhich python(Linux/macOS) илиwhere python(Windows) и переустановите.ERROR: [Errno 98] Address already in use— порт 8000 занят другим процессом. Укажите другой:--port 8001.TypeError: Object of type Decimal is not JSON serializable— вы возвращаете dict с типом, которыйjson.dumpsне поддерживает. Используйте Pydantic-модель или приведите тип вручную.- Swagger показывает пустой ответ без схемы — вы вернули
JSONResponseбез аннотации возвращаемого типа. Добавьте параметрresponse_modelв декоратор или верните Pydantic-модель. - Браузер показывает HTML вместо JSON — вы обратились к корневому пути
/, а эндпоинт висит на/status. Проверьте URL.
Что дальше
Вы умеете отдавать JSON тремя способами и проверять ответ без внешних инструментов. Следующие шаги:
- Добавьте POST-эндпоинт с телом запроса — Swagger позволит отправить JSON прямо из формы.
- Подключите базу данных через SQLAlchemy или Tortoise ORM и верните реальные данные вместо захардкоженных.
- Настройте CORS (
CORSMiddleware), если фронтенд живёт на другом домене — без этого браузер заблокирует ответ, хотя curl его получит. - Измерьте время ответа утилитой
heyилиwrk— и тогда решайте, нужен лиORJSONResponseна конкретном эндпоинте.
Проверка рекламы на риски: Что в макете вызовет вопросы ФАС: превосходные степени, сравнения, обещания результата, маркировка.
Спросить за 40 ₽Источники: FastAPI — официальная документация (Response Model, JSONResponse), Uvicorn — официальная документация
Частые вопросы
Обязательно ли использовать Pydantic-модели или можно просто возвращать dict?
Swagger UI не открывается по адресу /docs — что делать?
Чем отличается /docs от /redoc?
Что будет, если у меня более старая версия FastAPI — например, 0.95?
Можно ли использовать FastAPI без Uvicorn?
Как вернуть JSON с кодом 201 при создании ресурса?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.