JSON Schema · Draft 2020-12

Проверка JSON по JSON Schema

Вставьте JSON-данные слева, схему справа и получите кликабельный отчёт по структуре, типам и обязательным полям. Отдельный тумблер включает enum, const, диапазоны и другие ограничения значений.

Проверка выполняется в браузере Ограничения значений — по тумблеру Комментарии // и /* */ поддерживаются Нужно привести JSON в порядок? Открыть JSON Formatter →
Формат проверки
JSON-данные ↔ JSON SchemaСтруктурная проверка по Draft 2020-12
Дополнительные правила контракта
A JSON-данныеЭкземпляр, который проверяем
Готов к проверке
0 символов
B JSON SchemaDraft 2020-12 и локальные $ref
Готов к проверке
0 символов
Готов к проверке ⌘/Ctrl + Enter

Результат

Здесь появится отчёт JSON Schema

Вставьте JSON и схему или откройте пример. Каждый результат можно нажать, чтобы перейти к связанным строкам данных и схемы.

Сохранить сравнение

Создадим длинную уникальную ссылку, которая автоматически перестанет работать через 24 часа.

Кто сможет открыть

Сохранение выполняется только по вашему действию. Оба исходных JSON шифруются на сервере и удаляются после истечения срока.

От нуля до рабочего контракта

Что такое JSON Schema и как правильно её составить

JSON Schema — это машиночитаемое описание формы JSON-документа: какие узлы являются объектами или массивами, какие поля обязательны, какие типы допустимы и разрешены ли дополнительные свойства.

Схема применяется к экземпляру JSON. Она не является примером ответа и не содержит «правильные» данные: она задаёт правила, по которым любой будущий ответ можно признать подходящим или несовместимым.

01

Схема, экземпляр и словарь ключевых слов

У JSON Schema три слоя: данные, правила и выбранный диалект стандарта. Если разделить их в голове, даже большая схема остаётся предсказуемой.

instance

Экземпляр JSON

Конкретный документ, ответ API или конфигурация, которую вы проверяете. В редакторе он находится слева.

schema

Схема

JSON-объект либо boolean, который описывает допустимую структуру экземпляра. В редакторе он находится справа.

keyword

Ключевое слово

Стандартное правило вроде type, properties, required, items или oneOf. Каждое применяется к определённому типу узла.

dialect

Диалект / Draft

Версия словаря JSON Schema. URI в $schema сообщает инструментам, как понимать остальные ключевые слова.

02

Минимальная практическая схема объекта

Начинайте с корневого типа и постепенно сужайте контракт. 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 разрешает всё.
03

Как сформировать схему из существующего JSON

Автоматическая генерация даёт только черновик: один пример не показывает, что обязательно, что может быть null и какие варианты реально встречаются. Надёжная схема формируется в шесть проходов.

  1. 01

    Зафиксируйте назначение и Draft

    Выберите границу контракта — один API-ответ, событие или файл конфигурации — и добавьте $schema для Draft 2020-12.

  2. 02

    Разметьте тип каждого узла

    Объект получает type: object и properties, массив — type: array, примитивы — string, number, integer, boolean или null.

  3. 03

    Отделите известные поля от обязательных

    Перенесите поля в properties, но в required включайте только те, отсутствие которых действительно ломает контракт. Не выводите обязательность из одного примера.

  4. 04

    Определите политику расширения

    additionalProperties: false подходит закрытым внутренним контрактам. Для публичных API часто безопаснее разрешать новые поля, чтобы клиенты не ломались при эволюции.

  5. 05

    Смоделируйте массивы и варианты

    Для однородного списка используйте items. Для кортежа с разными позициями — prefixItems. Альтернативные формы выражайте anyOf или oneOf.

  6. 06

    Вынесите повторения и проверьте реальные образцы

    Повторяющиеся фрагменты перенесите в $defs и подключайте локальным $ref. Затем прогоните успешные и заведомо ошибочные JSON, чтобы проверить строгость схемы.

04

Какие варианты JSON Schema существуют

Схема не всегда выглядит как большой объект с properties. Стандарт допускает boolean-схемы, объединения типов, композицию и разные модели массивов.

Object schema

Объект с ключевыми словами

Основная форма: каждое ключевое слово добавляет правило или аннотацию.

{"type":"string"}
Boolean schema

Разрешить всё или ничего

true принимает любой экземпляр, false отклоняет любой. Удобно внутри items и additionalProperties.

true  /  false
Type union

Несколько допустимых типов

В 2020-12 nullable-значение обычно выражают массивом типов, без специального nullable.

{"type":["string","null"]}
Composition

Объединение нескольких схем

allOf требует все правила, anyOf — хотя бы одну ветку, oneOf — ровно одну ветку по полному стандарту.

{"oneOf":[{"type":"string"},{"type":"integer"}]}
Homogeneous array

Однородный список

Одна схема items применяется к каждому элементу массива.

{"type":"array","items":{"type":"string"}}
Tuple array

Кортеж по позициям

prefixItems задаёт отдельную схему каждой позиции; items описывает или запрещает хвост.

{"prefixItems":[{"type":"string"},{"type":"integer"}],"items":false}
05

Версии 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-04LegacyТолько поддержка уже существующего контракта.Устаревшие URI, id вместо $id и другие несовместимости. Для нового проекта не выбирайте.
OpenAPI 3.1Близок к 2020-12Схема является частью OpenAPI-документа.OAS 3.1 использует диалект JSON Schema 2020-12 с vocabulary OpenAPI. OAS 3.0 — более старое несовместимое подмножество с nullable.
06

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.
07

$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: данные остаются в браузере, поддерживаются только локальные ссылки.
08

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По стандарту должна совпасть ровно одна ветка. Без проверки значений выбирается ближайшая структурная ветка; с включённым тумблером проверяется ровно одно полное совпадение.
09

Что именно проверяет этот валидатор

JSON Schema — большой стандарт. Ниже перечислена фактическая поддержка текущего алгоритма и влияние тумблера значений.

Проверяется полностью

  • type, включая union типов и различие number / integer
  • properties, required, patternProperties, additionalProperties
  • minProperties, maxProperties, dependentRequired
  • items, prefixItems, minItems, maxItems
  • contains, 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 / contentSchema
  • unevaluatedProperties, unevaluatedItems, dependentSchemas, propertyNames
  • $dynamicRef, пользовательские vocabulary и внешние сетевые $ref
  • Инструмент ничего не загружает из интернета; внешние зависимости схемы нужно встроить через локальные $defs
10

Частые вопросы

Короткие ответы на решения, из-за которых схемы чаще всего становятся слишком строгими или, наоборот, ничего не проверяют.

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 обязателен.