Как обрабатываются незаполненные поля в ответе GET метода: возвращаются пустыми или отсутствуют
Что проверяют
Понимаете ли вы, что пустое поле в JSON бывает в трёх видах и что это часть контракта API, а не мелочь реализации. Следом обычно спрашивают, как отличить «не передано» от «обнулить» в PATCH и как это описать в схеме.
Как отвечать
Разведите три состояния:
- ключа нет: клиент не отличит «значения нет» от «старая версия сервера про поле не знает»;
null: поле есть в модели, значения у него нет;- пустое значение:
"",[],{}. Это уже значение, и для коллекций правильный ответ почти всегда[], а неnull.
Для GET разумный выбор по умолчанию: стабильная форма ответа, все поля схемы на месте, отсутствующее значение отдаётся как null. Клиентам со сгенерированными моделями на Kotlin, Swift или TypeScript так проще, а экономия трафика от выброшенных ключей обычно копеечная. Опускать поля есть смысл в разреженных ответах с десятками необязательных атрибутов, но тогда это правило для всего API.
В Python это настраивается явно:
- Pydantic v2 и FastAPI:
Noneпо умолчанию сериализуется вnull.model_dump(exclude_none=True)илиresponse_model_exclude_none=Trueвыкидывают такие поля, аexclude_unset=Trueвыкидывает то, что не задавали. На этом же строитсяPATCH: присланные поля видны вmodel_fields_set, иnullсреди них значит «очистить»; - DRF: сериализатор отдаёт все объявленные поля,
Noneуходит какnull, пустоту на входе разрешаютallow_nullиallow_blank; - OpenAPI: обязательность задаёт
required, допустимостьnullв версии 3.0 задаётnullable: true, в 3.1 это делается типом.
Где спотыкаются
Отвечают «как удобнее бэкенду» и смешивают подходы: в одном ресурсе пустой email приходит как "", в другом как null, в третьем ключа нет. Клиенту приходится писать три проверки.
Включают exclude_none на весь API. Поля, где null несёт смысл, вроде deleted_at или manager_id у сотрудника без руководителя, начинают то появляться, то пропадать.
В тестах проверяют ответ через data.get("email"). Такой тест не отличит отсутствующий ключ от null, и контракт незаметно поменяется. Проверяйте наличие ключа и значение отдельно.