JSON Schema

4 сентября 2026 · ~15 мин чтения

стандарт формат-данных json валидация контракты

JSON Schema

JSON Schema — это язык описания структуры JSON-документа, записанный сам на JSON. Схема отвечает на один вопрос: «подходит ли вот этот конкретный документ под наши правила — какие поля обязательны, какого они типа, в каких пределах значения». Это не формат данных и не база — это проверяющий, которого можно передать по сети.

История

Сначала был JSON. Дуглас Крокфорд (Douglas Crockford) в начале 2000-х вытащил из JavaScript подмножество синтаксиса объектов и объявил его форматом обмена данными — сайт json.org появился в 2002 году, первый стандарт RFC 4627 вышел в 2006-м. Формат победил XML в вебе примерно за пять лет по простой причине: он читался человеком и парсился браузером в одну строку.

И тут же вылезла дыра. У XML был XML Schema (XSD, стандарт W3C с 2001 года) и до него DTD — способ формально сказать «в этом документе элемент <order> обязан содержать <customer_id> целым числом». У JSON не было ничего. Каждый разработчик проверял входящие данные руками: if not isinstance(x, int): raise. Пятнадцать проверок на каждый эндпоинт, все написаны по-разному, все расползаются.

Кто и когда придумал. Первые черновики JSON Schema выпустил Крис Зип (Kris Zyp) — американский разработчик, известный по JavaScript-фреймворку Dojo Toolkit и работе в компании SitePen. Он опубликовал документ как Internet-Draft в IETF примерно в 2009–2010 годах (draft-zyp-json-schema-01 датирован 2010-м). Идея была нарочито рекурсивной: раз мы описываем JSON — давайте и описание тоже сделаем JSON-ом. Тогда схему можно хранить в той же базе, гонять по тому же HTTP и парсить теми же библиотеками, что и сами данные.

Вехи:

Текущий статус — важная тонкость. JSON Schema, несмотря на двадцатилетнюю историю и промышленное применение, формально так и не стала RFC. Она до сих пор существует в виде Internet-Draft — черновика IETF. При этом её поддерживают Kubernetes, OpenAPI, VS Code, Anthropic и OpenAI. Классический случай, когда де-факто стандарт обогнал де-юре стандарт лет на десять. Владельца в коммерческом смысле нет: спецификация открытая, разработка идёт на GitHub в организации json-schema-org.

Что это такое

Схема — это обычный JSON-объект, у которого ключи имеют особый смысл для валидатора. Вот схема для той самой задачи, из которой выросла эта статья, — записи в журнал проектов:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "skip":     { "type": "boolean" },
    "title":    { "type": "string", "maxLength": 70 },
    "what":     { "type": "string", "maxLength": 200 },
    "decision": { "type": "string", "maxLength": 400 },
    "memory":   { "type": "array", "items": { "type": "string" } }
  },
  "required": ["skip", "title", "what"],
  "additionalProperties": false
}

Читается почти по-человечески: это объект; у него есть поля такие-то; skip — булев, title — строка не длиннее 70 символов, memory — массив строк; три поля обязательны; ничего сверх перечисленного не пускать.

Дальше берётся валидатор — библиотека, которая принимает два JSON-а (схему и документ) и возвращает «да» или «нет, вот список нарушений». Всё. Схема ничего не делает сама: она не хранит данные, не преобразует их, не исправляет. Она только выносит вердикт.

Чем отличается от похожего:

Аналогии из жизни

1. Бланк в МФЦ. Схема — это бланк заявления: вот поля, вот звёздочки у обязательных, вот «дата в формате ДД.ММ.ГГГГ», вот «ИНН — 12 цифр». Приёмщик смотрит и заворачивает неправильно заполненное, не читая сути.

Где ломается: бланк и проверка — это один физический лист бумаги, они неразделимы. JSON Schema — только проверка, отдельно от документа. Данные существуют сами по себе и прекрасно живут без схемы; схема — это второй, необязательный предмет, который надо кому-то не забыть запустить. И ещё: бланк не даст физически написать 15 цифр в 12 клеточках, а схема ничего не запрещает заранее — она ругается уже постфактум.

2. ГОСТ на молоко. Стандарт говорит: жирность 2,5–3,2 %, объём 900–1000 мл, на этикетке обязателен состав. Лаборатория берёт пакет и проверяет по списку.

Где ломается: ГОСТ описывает ещё и процесс — как пастеризовать, при какой температуре везти. JSON Schema про процесс не знает вообще ничего, только про итоговый пакет. И ГОСТ обязателен по закону: нарушил — штраф. Схема не имеет никакой силы, пока конкретный программист не встроил валидатор в конкретное место кода. Схема, лежащая в репозитории и никем не вызываемая, — просто текстовый файл.

3. Досмотр в аэропорту. Проверка на входе, до попадания внутрь периметра: не пронесёшь больше 100 мл жидкости, ножницы длиннее определённой — в багаж. Отсекаем на границе, чтобы дальше в самолёте было спокойно.

Где ломается: досмотр ищет опасное содержимое, а схема — только форму. Строка "'; DROP TABLE users; --" — прекрасная валидная строка длиной меньше 70 символов, схема пропустит её не поморщившись. Проверка формы никогда не заменяет проверку смысла и не заменяет защиту от злого умысла.

Схема — не защита от атак

Валидная по схеме строка может содержать что угодно: SQL-инъекцию, скрипт, чужие персональные данные. JSON Schema отвечает на вопрос «правильной ли формы данные», а не «безопасны ли они». Санитизация, экранирование и права доступа — отдельная работа, схема её не делает.

Как это работает

Пошагово, что происходит в момент проверки.

Шаг 1. Валидатор получает два дерева. Документ (instance) и схему. Дальше он идёт по ним синхронно, как два курсора.

Шаг 2. Ключевые слова делятся на три сорта. Это главное, что стоит понять про устройство схемы:

Шаг 3. Открытость по умолчанию. Тут почти все обжигаются один раз.

Схема ничего не запрещает, пока ты не запретил явно

properties — это не список разрешённых полей. Это список полей, к которым применяются правила, ЕСЛИ они присутствуют. Документ {"title": "ок", "случайный_мусор": 42} пройдёт проверку. Чтобы отсечь лишнее, нужен "additionalProperties": false. Чтобы поле стало обязательным — required. Логика JSON Schema разрешительная: всё, что не описано, — можно.

Шаг 4. Ссылки и переиспользование. Повторять один и тот же кусок в схеме не надо: определяешь его один раз в $defs и ссылаешься через $ref, синтаксисом JSON Pointer (RFC 6901):

{
  "$defs": {
    "short_text": { "type": "string", "maxLength": 200 }
  },
  "properties": {
    "what": { "$ref": "#/$defs/short_text" },
    "tail": { "$ref": "#/$defs/short_text" }
  }
}

$ref умеет ссылаться и на внешний URL — то есть схема может собираться из нескольких файлов, лежащих на разных серверах. Отсюда же берётся возможность рекурсии: схема комментария, внутри которой список ответов той же схемы.

Шаг 5. Вердикт. На выходе — булев результат плюс список ошибок с указателями на конкретные места: /properties/title/maxLength, «строка длиной 94 при максимуме 70».

Шаг 6 (в продакшене). Компиляция. Наивный валидатор каждый раз заново обходит схему — медленно. Промышленные библиотеки (самый известный пример — Ajv, «Another JSON Validator», написанный Евгением Поберезкиным) при первом чтении компилируют схему в код: превращают дерево правил в развёрнутую функцию на JavaScript. Дальше проверка каждого документа — это вызов обычной скомпилированной функции, а не обход дерева. Разница на потоке — порядки.

Отдельный современный сюжет — LLM. Когда языковой модели говорят «верни строго JSON по этой схеме», у продвинутых реализаций работает не уговор, а механика: схема превращается в грамматику, и на каждом шаге генерации маскируются все токены, которые сделали бы документ невалидным. Модель физически не может выдать неправильную скобку. Это называется constrained decoding (генерация с ограничениями). У Anthropic описания инструментов (input_schema) — это JSON Schema; у OpenAI режим Structured Outputs принимает строгое подмножество JSON Schema. То есть схема из инструмента валидации превратилась ещё и в инструмент управления генерацией.

Где встречается в обычной жизни

Где встречается в IT и бизнесе

Кто пользуется

Альтернативы и конкуренты

Protocol Buffers (Protobuf, Google, 2008 в открытом доступе).
Плюсы: компактный бинарный формат, строгая типизация, генерация кода на десятке языков, встроенные правила эволюции схемы, отлично живёт с gRPC.
Минусы: данные нечитаемы глазом, без схемы вообще не расшифровать, отдельный язык описания и компилятор в цепочке сборки.

Apache Avro (2009, экосистема Hadoop).
Плюсы: лучшая в классе работа с эволюцией схемы — читатель и писатель могут иметь разные версии, и система сама разрулит; схема хранится вместе с данными; идеален для больших потоков в Kafka.
Минусы: за пределами мира больших данных почти не встречается, порог входа выше.

TypeScript-типы + Zod (или аналоги вроде Valibot).
Плюсы: пишешь схему прямо в коде, типы выводятся автоматически, сообщения об ошибках человеческие, разработчику удобно.
Минусы: живёт только внутри JavaScript/TypeScript, чужой Python-сервис твой Zod-объект не прочитает. Правда, Zod умеет экспортировать в JSON Schema — часто так и делают.

XML Schema (XSD, W3C, 2001).
Плюсы: очень выразителен, зрелые инструменты, до сих пор стандарт в госсекторе, банках и EDI.
Минусы: сам многословный XML, освоение — недели, для JSON-мира неприменим напрямую.

Когда НЕ стоит использовать

С чего начать на практике

Не пытайся описать схемой всё сразу. Возьми один файл, который люди правят руками и который ломает прод при опечатке — конфиг, тарифы, список фича-флагов. Напиши для него схему на 20 строк, повесь проверку в CI. Дальше станет понятно, где схема окупается, а где мешает.

Связанные понятия

Литература и источники

Где встретилось у меня

4 сентября батч-прогоном работал генератор записей в журнал проектов: каждая рабочая сессия сжимается моделью в одну короткую запись со строго заданными полями — что произошло, что решили, почему именно так. Задание модели — это, по сути, схема в чистом виде: перечень полей, обязательность, жёсткие лимиты длины по каждому, отдельный булев флаг «пропустить, тут писать не о чем». Ни одна из трёх десятков попыток в тот день не дошла до записи: все упали раньше, на несовместимости версии клиента с запрошенной моделью. Схема осталась незаполненной — что само по себе неплохая иллюстрация к тезису: схема ничего не гарантирует, пока кто-то не довёл до неё данные.

Краткое резюме