Найти в Дзене
Анастасия Софт

JSON Schema для новичков: легкая валидация

Оглавление

Привет! Ты когда-нибудь сталкивался с ситуацией, когда получаешь JSON-объект, а он не соответствует твоим ожиданиям? Например, в нём нет обязательного поля, тип данных не тот или значение выходит за пределы допустимого диапазона. Знакомо? Тогда тебе точно стоит познакомиться с JSON Schema — инструментом, который помогает описывать структуру данных и проверять их корректность.

Что такое JSON Schema?

JSON Schema — это спецификация, описывающая структуру JSON-данных. С помощью неё можно:

  • Убедиться, что данные соответствуют ожидаемой структуре.
  • Проверить типы данных.
  • Задать обязательные поля.
  • Ограничить значения (например, возраст должен быть больше 18).

Пример использования JSON Schema:

{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "integer", "minimum": 18 }
},
"required": ["name", "age"]
}

Этот пример описывает объект с двумя свойствами: name (строка) и age (целое число, не менее 18). Оба поля обязательны.

Основные типы данных в JSON Schema

JSON Schema поддерживает следующие типы данных:

  • string — строка.
  • number — число (включает как целые, так и вещественные числа).
  • integer — целое число.
  • boolean — логическое значение (true или false).
  • null — значение null.
  • object — объект (набор пар "ключ-значение").
  • array — массив.

Пример схемы для пользователя:

{
"type": "object",
"properties": {
"username": { "type": "string" },
"isActive": { "type": "boolean" }
}
}

Структура JSON Schema

Типичная структура JSON Schema включает:

  • $schema: указывает версию спецификации.
  • $id: уникальный идентификатор схемы.
  • title: название схемы.
  • description: описание схемы.
  • type: тип данных (например, object).
  • properties: описание свойств объекта.
  • required: список обязательных свойств.

Пример:

{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/user.schema.json",
"title": "User",
"description": "A user in the system",
"type": "object",
"properties": {
"username": { "type": "string" },
"email": { "type": "string", "format": "email" }
},
"required": ["username", "email"]
}

Примеры задач с разбором

1. Валидация простого объекта

Схема:

{
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "integer", "minimum": 18 }
},
"required": ["name", "age"]
}

Данные:

{ "name": "Alice", "age": 25 }

Результат: ✅ Данные валидны.

2. Проверка формата email

Схема:

{
"type": "object",
"properties": {
"email": { "type": "string", "format": "email" }
},
"required": ["email"]
}

Данные:

{ "email": "user@example.com" }

Результат: ✅ Данные валидны.

3. Ограничение на минимальный возраст

Схема:

{
"type": "object",
"properties": {
"age": { "type": "integer", "minimum": 18 }
},
"required": ["age"]
}

Данные:

{ "age": 16 }

Результат: ❌ Данные невалидны (возраст меньше 18).

4. Перечисление допустимых значений (enum)

Схема:

{
"type": "object",
"properties": {
"status": { "type": "string", "enum": ["active", "inactive", "pending"] }
},
"required": ["status"]
}

Данные:

{ "status": "active" }

Результат: ✅ Данные валидны.

5. Валидация массива

Схема:

{
"type": "array",
"items": { "type": "string" },
"minItems": 2
}

Данные:

["apple", "banana"]

Результат: ✅ Данные валидны.

6. Вложенные объекты

Схема:

{
"type": "object",
"properties": {
"address": {
"type": "object",
"properties": {
"street": { "type": "string" },
"city": { "type": "string" }
},
"required": ["street", "city"]
}
},
"required": ["address"]
}

Данные:

{ "address": { "street": "Main St", "city": "Somewhere" } }

Результат: ✅ Данные валидны.

7. Условная валидация (if/then/else)

Схема:

{
"type": "object",
"properties": {
"age": { "type": "integer" }
},
"if": {
"properties": { "age": { "type": "integer", "minimum": 18 } }
},
"then": {
"properties": { "age": { "maximum": 100 } }
},
"else": {
"properties": { "age": { "maximum": 17 } }
}
}

Данные:

{ "age": 20 }

Результат: ✅ Данные валидны.

Конечно! Давай ещё раз разберём использование регулярных выражений (RegExp) в JSON Schema — наглядно, живо и с комментариями.

🔍 Пример 8: Использование регулярных выражений

Регулярные выражения (pattern) в JSON Schema помогают проверять, соответствует ли строка определённому шаблону.

🎯 Задача:

Проверить, что строка является корректным номером автомобиля в формате "A123BC" (одна латинская буква, три цифры, две латинские буквы).

🧠 Схема с RegExp:

{
"type": "object",
"properties": {
"carNumber": {
"type": "string",
"pattern": "^[A-Z]{1}[0-9]{3}[A-Z]{2}$"
}
},
"required": ["carNumber"]
}

💬 Пояснение:

  • "^" — начало строки.
  • "[A-Z]{1}" — одна заглавная латинская буква.
  • "[0-9]{3}" — три цифры.
  • "[A-Z]{2}" — две заглавные латинские буквы.
  • "$" — конец строки.

💡 Важно: JSON Schema использует JavaScript-совместимый синтаксис RegExp. Экрапировать \ нужно двойным \\, если вы пишете внутри JSON-строки.

✅ Пример валидных данных:

{ "carNumber": "A123BC" }

🟢 Всё отлично — соответствует шаблону.

❌ Примеры невалидных данных:

{ "carNumber": "AB123C" }

🔴 Не соответствует: порядок символов не такой.

{ "carNumber": "A123B" }

🔴 Не соответствует: не хватает одной буквы в конце.

{ "carNumber": "a123bc" }

🔴 Не соответствует: буквы не заглавные (нужны A-Z, а не a-z).

📦 Бонус: RegExp для валидации других форматов

-2

📚 Вывод

Регулярные выражения в JSON Schema — мощный инструмент для точной валидации строковых значений. Главное — не забывать, что:

  • pattern работает только с типом string.
  • Он применяет JavaScript RegExp-синтаксис.
  • Экрапирование — боль, но нужная боль (\\ вместо \ в JSON).

9. Валидация уникальных элементов массива

Схема:

{
"type": "object",
"properties": {
"tags": {
"type": "array",
"items": { "type": "string" },
"uniqueItems": true
}
},
"required": ["tags"]
}

💬 Что это делает:

Гарантирует, что в массиве tags все элементы уникальны.

Данные:

{ "tags": ["news", "tech", "news"] }

❌ Результат: данные невалидны — дубликат "news".

10. Использование allOf, anyOf, oneOf

allOf — все условия должны быть выполнены.

anyOf — достаточно хотя бы одного.

oneOf — должно выполняться ровно одно.

Пример с oneOf:

{
"type": "object",
"properties": {
"identifier": {
"oneOf": [
{ "type": "string", "pattern": "^user_[a-z]+$" },
{ "type": "integer", "minimum": 1 }
]
}
},
"required": ["identifier"]
}

💬 Что это делает:

identifier может быть либо строкой, начинающейся с "user_", либо положительным числом — но не обоими сразу.

Данные:

{ "identifier": 42 }

✅ Валидно.

{ "identifier": "user_alice" }

✅ Тоже валидно.

{ "identifier": "user_alice", "identifier": 1 }

❌ Невалидно — два условия сразу.

🎓 Где и как применять JSON Schema?

Вот реальные кейсы:

  1. 🔧 Валидация API запросов/ответов (в OpenAPI/Swagger).
  2. 🧪 Проверка JSON-конфигов в CI/CD.
  3. 🎮 Валидация игровых настроек (например, JSON-файлов от модов).
  4. 📄 Проверка пользовательских шаблонов (например, резюме в JSON).
  5. 🧾 Проверка данных из форм до отправки на сервер.
  6. 💬 Валидация WebSocket сообщений (особенно, если там JSON).
  7. 🛡 Безопасность: защита от "грязных" данных.
  8. 🧩 Генерация форм по JSON Schema (например, react-jsonschema-form).
  9. 🔍 Линтинг и автодополнение в редакторах кода.
  10. 📦 Обеспечение совместимости между микросервисами.

🔧 Как валидировать JSON?

Есть множество валидаторов. Вот примеры:

  • Node.js (Ajv):npm install ajv
    const Ajv = require("ajv");
    const ajv = new Ajv();
    const validate = ajv.compile(schema);
    const valid = validate(data);
  • Python (jsonschema):pip install jsonschema
    from jsonschema import validate
    validate(instance=data, schema=schema)

🧠 Заключение

JSON Schema — это как строгий, но справедливый учитель: сначала кажется сложным, но потом ты начинаешь ценить порядок. Он:

✅ Упрощает разработку.

✅ Помогает ловить ошибки раньше.

✅ Отлично документирует структуру данных.

Что дальше?

  • Попробуй написать свою первую схему.
  • Добавь валидацию на сервер.
  • Валидацию в CI/CD пайплайн.
  • И наконец — расслабься, ты теперь знаешь больше, чем большинство разработчиков про JSON Schema 😄