FastAPI принимает «yes» вместо true: когда нужна строгая модель JSON
Команда включения автоматического продления должна содержать JSON true или false. Однако API принимает строки «yes», «0» и числа. На первый взгляд это удобно: Pydantic приводит распространённые формы к bool. Но при согласованном машинном контракте такое приведение скрывает ошибки клиента и усложняет проверку того, что он действительно отправляет.
Выберите строгий тип на нужной границе
Обычный bool и StrictBool отвечают на разные вопросы. Первый пытается получить логическое значение из поддерживаемого ввода. Второй требует настоящее логическое значение. Для JSON это практически полезно: true и false — самостоятельные типы, отличные от строки "true" и числа 1. Pydantic не обязан исправлять клиентский сериализатор, который потерял тип.
Не переносите это правило автоматически на URL. Query-параметры приходят текстом: строка ?enabled=true не содержит JSON-тип bool. Для query часто полезно штатное преобразование FastAPI или явно выбранные строковые значения. Строгость определяйте для каждого транспорта, а не включайте для всего приложения без разбора.
Проверьте принятие и отказ одним тестом
В примере настройка меняется через JSON-тело. Ответ содержит значение, дошедшее до обработчика. Тест отправляет обе допустимые формы и несколько типичных ошибок. В нём число 1 проверяется отдельно от true: в Python эти значения равны при обычном сравнении, но контракт JSON различает их.
Сохраните весь блок в файл и запустите Python 3.11+ в отдельном окружении с пакетами fastapi, httpx. Для моделей используется Pydantic v2; отдельный сервер для TestClient не нужен.
from fastapi import FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel, StrictBool
app = FastAPI()
class Renewal(BaseModel):
enabled: StrictBool
@app.put("/renewal")
def renewal(data: Renewal):
return data
with TestClient(app) as client:
for value in (True, False):
response = client.put("/renewal", json={"enabled": value})
assert response.status_code == 200
assert response.json()["enabled"] is value
for value in ("true", "yes", "0", 1, 0, None):
response = client.put("/renewal", json={"enabled": value})
assert response.status_code == 422
assert response.json()["detail"][0]["loc"] == ["body", "enabled"]
print("only JSON booleans accepted")Как читать результат
Успешное преобразование не равно успешному соблюдению договора. В этом сценарии ошибка 422 полезнее молчаливого принятия строки: разработчик интерфейса видит дефект до того, как команда изменит состояние. Возвращать 500 здесь неверно, потому что сервер работает и отклоняет входные данные по заявленному правилу.
Строгий тип не решает, кому разрешено менять настройку. Проверка пользователя должна выполняться отдельно. Он также не запрещает неизвестные ключи: если команда должна отклонять лишние поля, добавьте extra="forbid" как независимое правило. В тестах хорошо иметь отдельный пример на каждое решение, чтобы отказ сразу указывал на сломанный контракт.
Как изменить существующий API
Перед включением StrictBool посмотрите примеры SDK и запросов вашего интерфейса. Некоторые языки сериализуют значение из HTML-формы строкой. Исправьте преобразование на стороне клиента и добавьте его проверку. Если вы управляете несколькими версиями клиентов, согласуйте переход: мгновенное ужесточение может превратить привычные запросы в 422.
Оставьте в OpenAPI понятное описание поля с примером JSON. При этом сама схема boolean ещё не всегда объясняет поведение всех приводящих типов: регрессионный HTTP-тест остаётся точным исполняемым договором. Существующая статья о PATCH и false объясняет сохранение уже разобранного значения; здесь мы определяем, какие значения вообще разрешено разобрать.
Следующая практика
В открытом уроке об ограничениях Pydantic вы проверите входные значения и увидите, как API возвращает ошибки формы. После этого сравните обычный bool и StrictBool на JSON-команде из статьи. Откройте урок о валидации и выполните проверку полей.
Дальше полезно связать валидацию с сохранением настройки и правами пользователя. В бесплатной программе FastAPI эти части соединяются в один API с базой и тестами. Откройте программу курса.
Продолжить на практике
- FastAPI для начинающих: API с базой данных и тестами ↗
Соберёте свой первый полноценный backend на FastAPI: с базой данных, регистрацией, JWT-авторизацией и автотестами. 34 коротких урока и 140 заданий с проверкой — бесплатно.
