JSON Schema: чем отличаются обязательное поле, null и пустая строка
Матрица required, nullable и minLength: четыре синтетических документа и проверка присутствия поля для частичного обновления.
Поле может отсутствовать, присутствовать со значением null или содержать пустую строку. Это три разных документа. Если API сводит их к одному состоянию, оно может очистить значение вместо сохранения или принять неполные данные вместо ошибки.
В JSON Schema обязательность и допустимый тип задаются отдельно. required проверяет присутствие свойства; он не означает автоматически «не null» или «не пустая строка». null — самостоятельный тип, а не обозначение отсутствия. Официальное руководство JSON Schema о null.
Схема с обязательным nullable-полем
Учебный объект содержит nickname. Допустимы непустая строка или явный null, но поле обязательно:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["nickname"],
"properties": {
"nickname": {"type": ["string", "null"], "minLength": 1}
}
}
Вставьте схему и один синтетический документ в JSON Schema validator Neraviko. Ожидаемая матрица правил:
| Документ | Соответствие | Причина |
|---|---|---|
{} |
false | Нет обязательного свойства |
{"nickname":null} |
true | Поле есть, null разрешён |
{"nickname":""} |
false | Строка короче minLength |
{"nickname":"Demo"} |
true | Непустая строка |
minLength ограничивает строки. Он не отменяет разрешение null из списка типов. Правила длины описаны в JSON Schema Validation 2020-12.
Этот пример не описывает политику реального профиля пользователя. Решение разрешить очистку или пустое имя принадлежит вашему продукту. Схема должна выражать принятое решение, а не выбирать его за команду.
Четыре варианта контракта
Если поле обязательно и должно всегда быть строкой, оставьте required, задайте type: "string" и при необходимости minLength. Если оно обязательно, но может быть null, используйте массив типов как выше.
Если поле необязательно, уберите его имя из required. Одного присутствия в properties недостаточно, чтобы сделать его обязательным. Это правило часто пропускают, когда копируют шаблон схемы. JSON Schema: required properties.
Необязательная строка без null — тоже полезный контракт: {} проходит, {"nickname":null} не проходит. «Необязательное» здесь означает возможность отсутствия, а не возможность подставить любое пустое значение. Добавление null в список типов меняет принимаемые документы.
Частичное обновление требует своего соглашения
В учебном API договоримся: отсутствие nickname оставляет прежнее имя, null очищает его, непустая строка заменяет. Это наше явно заданное соглашение, не общий закон всех PATCH API. Для входа такого обновления свойство будет необязательным и nullable.
Присутствие можно проверить без смешивания значений в JavaScript:
function classify(source) {
const value = JSON.parse(source);
if (!Object.hasOwn(value, "nickname")) return "absent";
if (value.nickname === null) return "null";
if (value.nickname === "") return "empty string";
return "value";
}
for (const sample of ["{}", '{"nickname":null}',
'{"nickname":""}', '{"nickname":"Demo"}']) {
console.log(classify(sample));
}
Вывод: absent, null, empty string, value, по одному состоянию на строку. Это диагностика присутствия, а не полноценная валидация схемы. Перед применением обновления приложение должно проверить тип, длину и полномочия.
Проверка вида if (!value.nickname) не подходит: она смешивает отсутствие, null, пустую строку и другие falsy-значения. В контракте обновления такое смешивание особенно опасно. Сохраните четыре отдельных синтетических случая в регрессионных тестах.
Ошибка данных и ошибка схемы
В Neraviko несовпадение со схемой возвращает valid=false и статус needs_review. Это завершённая проверка, поэтому HTTP 200 сам по себе не означает, что поле подходит. Читайте нарушения, путь данных и путь правила.
Некорректный JSON или неподдерживаемая схема — другой результат: error envelope с HTTP 422. Если схема не разбирается, исправляйте документ схемы. Если нарушено required, решите, должен ли отправитель заполнить поле, а не удаляйте правило ради успешного ответа.
Neraviko поддерживает ограниченное подмножество Draft 2020-12. Удалённые и рекурсивные ссылки не поддерживаются; обычное поле с локальным правилом выше не требует ссылок. default не следует считать приказом валидатору вставить значение: валидация проверяет данные, а политика заполнения принадлежит приложению.
Обработка данных и схемы серверная. Используйте синтетические профили, как здесь, вместо настоящих персональных сведений. Лимиты — 262 144 байта данных и 65 536 байт схемы с дополнительными общими ограничениями. Если схема проходит, это подтверждает только её правила; происхождение данных и смысл изменения должны проверяться отдельно.