Валидация JSON Schema: полное руководство
JSON Schema — это словарь для аннотирования и валидации документов JSON. Он обеспечивает контракт для ваших данных — определяя, какую форму они должны иметь, какие типы допустимы и какие поля обязательны. Если вы работаете с API, конфигурационными файлами или любыми структурированными данными, JSON Schema — незаменимый инструмент в вашем арсенале.
Зачем использовать JSON Schema?
Без валидации данные JSON — это кот в мешке. Вы можете получить поле возраста в виде строки, отсутствующий email или дату в неправильном формате. JSON Schema перехватывает эти проблемы на границе, до того как некорректные данные распространятся по вашей системе.
Ключевые преимущества:
- Соблюдение контрактов API: Автоматическая валидация тел запросов и ответов
- Документация: Схема служит живой документацией для ваших структур данных
- Генерация кода: Инструменты могут генерировать типы, формы и схемы баз данных из JSON Schema
- Тестирование: Валидация тестовых данных и моков по схеме
Базовая структура схемы
Каждая JSON Schema начинается с нескольких стандартных свойств:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/user.schema.json",
"title": "User",
"description": "A registered user in the system",
"type": "object",
"properties": {
"id": { "type": "integer", "minimum": 1 },
"name": { "type": "string", "minLength": 1, "maxLength": 100 },
"email": { "type": "string", "format": "email" },
"age": { "type": "integer", "minimum": 0, "maximum": 150 }
},
"required": ["id", "name", "email"]
}
Используйте наш JSON Formatter, чтобы отформатировать ваши схемы для удобства чтения перед тем, как делиться ими с командой.
Ограничения типов
JSON Schema поддерживает шесть примитивных типов:
| Тип | Описание | Пример |
|---|---|---|
string | Текстовые данные | "hello" |
number | Любое числовое значение | 3.14 |
integer | Только целые числа | 42 |
boolean | Истина или ложь | true |
array | Упорядоченный список | [1, 2, 3] |
object | Пары ключ-значение | {"key": "value"} |
null | Пустое значение | null |
Строковые ограничения
{
"type": "string",
"minLength": 1,
"maxLength": 255,
"pattern": "^[A-Za-z0-9]+$",
"format": "email"
}
Встроенные форматы включают: email, uri, date, date-time, ipv4, ipv6, uuid и hostname.
Числовые ограничения
{
"type": "number",
"minimum": 0,
"maximum": 100,
"exclusiveMinimum": 0,
"multipleOf": 0.01
}
Валидация массивов
Массивы можно валидировать по элементам, длине и уникальности:
{
"type": "array",
"items": { "type": "string", "format": "email" },
"minItems": 1,
"maxItems": 10,
"uniqueItems": true
}
Для валидации кортежей (массивов фиксированной длины с определёнными типами для каждой позиции):
{
"type": "array",
"prefixItems": [
{ "type": "number" },
{ "type": "string" },
{ "type": "boolean" }
],
"items": false
}
Валидация объектов
Объекты поддерживают валидацию свойств, обязательные поля и контроль дополнительных свойств:
{
"type": "object",
"properties": {
"name": { "type": "string" },
"role": { "enum": ["admin", "editor", "viewer"] }
},
"required": ["name", "role"],
"additionalProperties": false
}
Установка additionalProperties в false — это строгий режим, который отклоняет любые свойства, не определённые в схеме. Это особенно полезно для API, где вы хотите перехватить опечатки в именах полей.
Ключевые слова композиции
JSON Schema поддерживает комбинирование схем с помощью логических операторов:
allOf (И)
Данные должны быть валидны по отношению ко всем подсхемам:
{
"allOf": [
{ "$ref": "#/$defs/baseUser" },
{ "properties": { "role": { "const": "admin" } } }
]
}
oneOf (исключающее ИЛИ)
Данные должны быть валидны ровно по одной из подсхем:
{
"oneOf": [
{ "properties": { "type": { "const": "email" }, "email": { "type": "string" } } },
{ "properties": { "type": { "const": "phone" }, "phone": { "type": "string" } } }
]
}
anyOf (ИЛИ)
Данные должны быть валидны хотя бы по одной из подсхем.
Условная валидация
Ключевые слова if/then/else обеспечивают условную валидацию:
{
"type": "object",
"properties": {
"country": { "type": "string" },
"postalCode": { "type": "string" }
},
"if": {
"properties": { "country": { "const": "US" } }
},
"then": {
"properties": { "postalCode": { "pattern": "^[0-9]{5}(-[0-9]{4})?$" } }
},
"else": {
"properties": { "postalCode": { "pattern": "^[A-Z0-9 -]+$" } }
}
}
Ссылки и повторное использование
Используйте $ref для ссылок на многоразовые определения:
{
"$defs": {
"address": {
"type": "object",
"properties": {
"street": { "type": "string" },
"city": { "type": "string" },
"country": { "type": "string" }
},
"required": ["street", "city", "country"]
}
},
"type": "object",
"properties": {
"billingAddress": { "$ref": "#/$defs/address" },
"shippingAddress": { "$ref": "#/$defs/address" }
}
}
Валидация на практике
JavaScript (Ajv)
const Ajv = require('ajv');
const ajv = new Ajv();
const validate = ajv.compile(schema);
const valid = validate(data);
if (!valid) console.log(validate.errors);
Python (jsonschema)
from jsonschema import validate, ValidationError
try:
validate(instance=data, schema=schema)
except ValidationError as e:
print(f"Validation error: {e.message}")
Для быстрой валидации без настройки среды разработки вставьте ваш JSON и схему в наш JSON Validator.
Практический пример: схема ответа API
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"status": { "enum": ["success", "error"] },
"data": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" },
"createdAt": { "type": "string", "format": "date-time" }
},
"required": ["id", "name"]
}
},
"pagination": {
"type": "object",
"properties": {
"page": { "type": "integer", "minimum": 1 },
"perPage": { "type": "integer", "minimum": 1, "maximum": 100 },
"total": { "type": "integer", "minimum": 0 }
}
}
},
"required": ["status", "data"]
}
Часто задаваемые вопросы
В чём разница между JSON Schema draft-07 и 2020-12?
Draft 2020-12 внёс несколько улучшений: prefixItems заменил кортежную форму items, $dynamicRef обеспечивает более гибкие ссылки, а поддержка словарей позволяет создавать пользовательские расширения. Для новых проектов используйте 2020-12. Для совместимости со старыми инструментами draft-07 по-прежнему широко поддерживается.
Может ли JSON Schema валидировать вложенный JSON внутри строкового поля?
Нет, напрямую. JSON Schema валидирует структуру разобранного JSON. Если поле содержит JSON-строку, вам нужно сначала разобрать её и валидировать отдельно. Некоторые валидаторы предлагают пользовательские валидаторы формата, которые могут обработать это, но это не является частью стандарта.
Связанные ресурсы
- JSON Formatter — Форматируйте и украшайте ваши JSON-схемы
- Как валидировать JSON — Распространённые ошибки валидации JSON и их исправления
- Паттерны проектирования JSON API — Создание лучших REST API с JSON