Проверка JSON по JSON Schema
Вставьте JSON-данные слева, схему справа и получите кликабельный отчёт по структуре, типам и обязательным полям. Отдельный тумблер включает enum, const, диапазоны и другие ограничения значений.
Результат
Вставьте JSON и схему или откройте пример. Каждый результат можно нажать, чтобы перейти к связанным строкам данных и схемы.
Что такое JSON Schema и как правильно её составить
JSON Schema — это машиночитаемое описание формы JSON-документа: какие узлы являются объектами или массивами, какие поля обязательны, какие типы допустимы и разрешены ли дополнительные свойства.
Схема применяется к экземпляру JSON. Она не является примером ответа и не содержит «правильные» данные: она задаёт правила, по которым любой будущий ответ можно признать подходящим или несовместимым.
Схема, экземпляр и словарь ключевых слов
У JSON Schema три слоя: данные, правила и выбранный диалект стандарта. Если разделить их в голове, даже большая схема остаётся предсказуемой.
instanceЭкземпляр JSON
Конкретный документ, ответ API или конфигурация, которую вы проверяете. В редакторе он находится слева.
schemaСхема
JSON-объект либо boolean, который описывает допустимую структуру экземпляра. В редакторе он находится справа.
keywordКлючевое слово
Стандартное правило вроде type, properties, required, items или oneOf. Каждое применяется к определённому типу узла.
dialectДиалект / Draft
Версия словаря JSON Schema. URI в $schema сообщает инструментам, как понимать остальные ключевые слова.
Минимальная практическая схема объекта
Начинайте с корневого типа и постепенно сужайте контракт. properties описывает известные поля, а required отдельно говорит, какие из них обязаны присутствовать.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/schemas/user.json",
"title": "User",
"type": "object",
"required": ["id", "email"],
"additionalProperties": false,
"properties": {
"id": {"type": "integer"},
"email": {"type": "string"},
"roles": {
"type": "array",
"items": {"type": "string"}
}
}
}
$schema- URI диалекта. Для новых схем обычно выбирают Draft 2020-12.
$id- Стабильный идентификатор схемы и база для разрешения ссылок. Не обязан совпадать с адресом файла.
type- Допустимый JSON-тип: object, array, string, number, integer, boolean или null.
properties- Словарь схем для известных свойств объекта. Само наличие здесь ещё не делает поле обязательным.
required- Массив имён полей, которые должны присутствовать в объекте.
additionalProperties- false запрещает неизвестные поля; объект-схема задаёт правила для них; true разрешает всё.
Как сформировать схему из существующего JSON
Автоматическая генерация даёт только черновик: один пример не показывает, что обязательно, что может быть null и какие варианты реально встречаются. Надёжная схема формируется в шесть проходов.
- 01
Зафиксируйте назначение и Draft
Выберите границу контракта — один API-ответ, событие или файл конфигурации — и добавьте $schema для Draft 2020-12.
- 02
Разметьте тип каждого узла
Объект получает type: object и properties, массив — type: array, примитивы — string, number, integer, boolean или null.
- 03
Отделите известные поля от обязательных
Перенесите поля в properties, но в required включайте только те, отсутствие которых действительно ломает контракт. Не выводите обязательность из одного примера.
- 04
Определите политику расширения
additionalProperties: false подходит закрытым внутренним контрактам. Для публичных API часто безопаснее разрешать новые поля, чтобы клиенты не ломались при эволюции.
- 05
Смоделируйте массивы и варианты
Для однородного списка используйте items. Для кортежа с разными позициями — prefixItems. Альтернативные формы выражайте anyOf или oneOf.
- 06
Вынесите повторения и проверьте реальные образцы
Повторяющиеся фрагменты перенесите в $defs и подключайте локальным $ref. Затем прогоните успешные и заведомо ошибочные JSON, чтобы проверить строгость схемы.
Какие варианты JSON Schema существуют
Схема не всегда выглядит как большой объект с properties. Стандарт допускает boolean-схемы, объединения типов, композицию и разные модели массивов.
Объект с ключевыми словами
Основная форма: каждое ключевое слово добавляет правило или аннотацию.
{"type":"string"}Разрешить всё или ничего
true принимает любой экземпляр, false отклоняет любой. Удобно внутри items и additionalProperties.
true / falseНесколько допустимых типов
В 2020-12 nullable-значение обычно выражают массивом типов, без специального nullable.
{"type":["string","null"]}Объединение нескольких схем
allOf требует все правила, anyOf — хотя бы одну ветку, oneOf — ровно одну ветку по полному стандарту.
{"oneOf":[{"type":"string"},{"type":"integer"}]}Однородный список
Одна схема items применяется к каждому элементу массива.
{"type":"array","items":{"type":"string"}}Кортеж по позициям
prefixItems задаёт отдельную схему каждой позиции; items описывает или запрещает хвост.
{"prefixItems":[{"type":"string"},{"type":"integer"}],"items":false}Версии JSON Schema: Draft 2020-12, 2019-09, 07 и OpenAPI
Draft — не версия вашего документа, а версия языка схемы. Не смешивайте синтаксис разных drafts без явной причины: особенно различается описание tuple-массивов и повторно используемых определений.
| Диалект | Статус | Когда выбирать | Что помнить |
|---|---|---|---|
| Draft 2020-12 | Рекомендуется | Новые независимые схемы и современные инструменты. | prefixItems для кортежей, $defs, dynamicRef и уточнённая модель массивов. На этот draft ориентирован наш валидатор. |
| Draft 2019-09 | Современный | Существующая экосистема уже закреплена на 2019-09. | $defs и unevaluatedProperties уже есть, но массивы устроены до разделения items/prefixItems. |
| Draft-07 | Очень распространён | Старые API, генераторы кода и библиотеки без 2020-12. | Определения часто лежат в definitions, а tuple задаётся массивом внутри items. При переносе нужна конвертация. |
| Draft-06 / Draft-04 | Legacy | Только поддержка уже существующего контракта. | Устаревшие URI, id вместо $id и другие несовместимости. Для нового проекта не выбирайте. |
| OpenAPI 3.1 | Близок к 2020-12 | Схема является частью OpenAPI-документа. | OAS 3.1 использует диалект JSON Schema 2020-12 с vocabulary OpenAPI. OAS 3.0 — более старое несовместимое подмножество с nullable. |
items, prefixItems и contains
Сначала решите, массив — список однотипных сущностей или кортеж фиксированных позиций. Это два разных контракта.
{
"type": "array",
"prefixItems": [
{"type": "string"},
{"type": "integer"}
],
"items": false,
"minItems": 2,
"maxItems": 2
}
- items с объектом-схемой проверяет каждый элемент однородного списка.
- prefixItems описывает позиции 0, 1, 2…; items применяется к оставшемуся хвосту.
- contains проверяет, что хотя бы несколько элементов подходят отдельной схеме; количество регулируют minContains и maxContains.
$defs и локальные $ref
Повторяемые фрагменты лучше хранить один раз. $defs — обычный контейнер схем, а $ref указывает на них JSON Pointer-путём.
{
"$defs": {
"id": {"type": "integer"}
},
"type": "object",
"properties": {
"userId": {"$ref": "#/$defs/id"},
"teamId": {"$ref": "#/$defs/id"}
}
}
- # обозначает корень текущей схемы; #/$defs/id — локальный JSON Pointer.
- Сегменты с / и ~ экранируются как ~1 и ~0.
- Этот инструмент не загружает внешние URL в $ref: данные остаются в браузере, поддерживаются только локальные ссылки.
allOf, anyOf и oneOf
Композиция нужна, когда один объект наследует общие правила или допускает несколько структурных форм. Ветки должны отличаться достаточно явно, иначе oneOf становится неоднозначным.
{
"oneOf": [
{
"type": "object",
"required": ["email"],
"properties": {"email": {"type": "string"}}
},
{
"type": "object",
"required": ["phone"],
"properties": {"phone": {"type": "string"}}
}
]
}
allOfЭкземпляр должен пройти каждую ветку. Это пересечение правил, а не наследование с автоматическим слиянием properties.anyOfДостаточно хотя бы одной подходящей ветки. Несколько веток могут совпасть одновременно.oneOfПо стандарту должна совпасть ровно одна ветка. Без проверки значений выбирается ближайшая структурная ветка; с включённым тумблером проверяется ровно одно полное совпадение.
Что именно проверяет этот валидатор
JSON Schema — большой стандарт. Ниже перечислена фактическая поддержка текущего алгоритма и влияние тумблера значений.
Проверяется полностью
type, включая union типов и различие number / integerproperties,required,patternProperties,additionalPropertiesminProperties,maxProperties,dependentRequireditems,prefixItems,minItems,maxItemscontains,minContains,maxContains- boolean-схемы,
allOf, локальные$refи ссылки в$defs
Проверяется структурно
anyOf— ищется хотя бы одна структурно подходящая веткаoneOf— без проверки значений выбирается лучшая структурная ветка- Порядок ключей и элементов — дополнительная настройка инструмента, а не стандартное правило JSON Schema
$schema,$id, title, description, default и examples читаются как аннотации и не влияют на результат
По тумблеру «Проверять значения»
- Конкретные значения:
enum,const - Строки:
pattern,minLength,maxLength - Числа:
minimum,maximum,exclusiveMinimum,exclusiveMaximum,multipleOf uniqueItems,not,if/then/elseи точностьoneOf
Пока не проверяется
format(email, URI, date-time) и contentEncoding / contentMediaType / contentSchemaunevaluatedProperties,unevaluatedItems,dependentSchemas,propertyNames$dynamicRef, пользовательские vocabulary и внешние сетевые$ref- Инструмент ничего не загружает из интернета; внешние зависимости схемы нужно встроить через локальные
$defs
Частые вопросы
Короткие ответы на решения, из-за которых схемы чаще всего становятся слишком строгими или, наоборот, ничего не проверяют.
properties автоматически делает поля обязательными?
Нет. properties только задаёт правила для поля, если оно присутствует. Обязательные имена перечисляются отдельно в required родительского объекта.
Нужно ли всегда ставить additionalProperties: false?
Нет. Это полезно для закрытого контракта, но может ломать потребителей публичного API при добавлении безобидных полей. Выбирайте политику эволюции осознанно.
Как разрешить string или null?
В Draft 2020-12 используйте type: ["string", "null"]. Ключ nullable относится главным образом к OpenAPI 3.0 и не является стандартным JSON Schema keyword.
Чем integer отличается от number?
integer принимает только числа без дробной части, а number — и целые, и дробные. JSON не имеет отдельных 32/64-битных числовых типов.
Можно ли построить схему по одному примеру автоматически?
Можно получить черновик типов и вложенности, но нельзя надёжно вывести required, nullable, альтернативы и политику дополнительных полей. Эти решения требуют знаний о контракте.
Почему валидатор не ругается на неправильный email или enum?
enum проверяется после включения тумблера «Проверять значения». format, включая email, пока не проверяется: используйте pattern либо полноценный стандартный валидатор, если format обязателен.