Понимание JSON Schema: Полное руководство по валидации данных
Исчерпывающее руководство по JSON Schema: создание схем, валидация данных, ключевые слова, примеры использования и лучшие практики для надежной работы с данными.
Big JSON Team
• Technical WriterExpert in JSON data manipulation, API development, and web technologies. Passionate about creating tools that make developers' lives easier.
# Понимание JSON Schema: Полное руководство по валидации данных
JSON Schema — это мощный инструмент для описания и валидации структуры JSON данных. В этом подробном руководстве мы рассмотрим все аспекты JSON Schema: от базовых концепций до продвинутых техник валидации.
Что такое JSON Schema?
JSON Schema — это словарь (vocabulary), который позволяет аннотировать и валидировать JSON документы. Это сам JSON документ, описывающий структуру других JSON документов.
Зачем нужен JSON Schema?
- Валидация данных — проверка соответствия структуре
- Документация — описание формата API
- Генерация кода — автоматическое создание типов
- Автодополнение — в IDE и редакторах
- Тестирование — проверка контрактов API
Простой пример
Данные:{
"имя": "Иван Петров",
"возраст": 30,
"email": "ivan@example.com"
}
Schema:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"имя": {
"type": "string",
"minLength": 1
},
"возраст": {
"type": "integer",
"minimum": 0,
"maximum": 150
},
"email": {
"type": "string",
"format": "email"
}
},
"required": ["имя", "возраст"]
}
Базовые типы данных
string
{
"type": "string",
"minLength": 1,
"maxLength": 100,
"pattern": "^[А-Яа-я]+$"
}
Примеры валидных значений:
"Иван""Мария""Александр"
number и integer
{
"возраст": {
"type": "integer",
"minimum": 0,
"maximum": 150
},
"цена": {
"type": "number",
"minimum": 0,
"multipleOf": 0.01
}
}
boolean
{
"активен": {
"type": "boolean"
}
}
null
{
"отчество": {
"type": ["string", "null"]
}
}
array
{
"теги": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"maxItems": 10,
"uniqueItems": true
}
}
object
{
"адрес": {
"type": "object",
"properties": {
"город": {"type": "string"},
"улица": {"type": "string"},
"дом": {"type": "string"}
},
"required": ["город"]
}
}
Ключевые слова валидации
required
{
"type": "object",
"properties": {
"имя": {"type": "string"},
"email": {"type": "string"}
},
"required": ["имя", "email"]
}
enum
{
"статус": {
"type": "string",
"enum": ["активен", "неактивен", "заблокирован"]
},
"роль": {
"enum": ["admin", "user", "guest"]
}
}
const
{
"версия": {
"const": "1.0.0"
}
}
minLength, maxLength
{
"пароль": {
"type": "string",
"minLength": 8,
"maxLength": 128
}
}
minimum, maximum
{
"оценка": {
"type": "integer",
"minimum": 1,
"maximum": 5
},
"скидка": {
"type": "number",
"minimum": 0,
"maximum": 100,
"exclusiveMaximum": false
}
}
pattern
{
"телефон": {
"type": "string",
"pattern": "^\+7-\d{3}-\d{3}-\d{2}-\d{2}$"
},
"почтовый_индекс": {
"type": "string",
"pattern": "^\d{6}$"
}
}
format
{
"email": {
"type": "string",
"format": "email"
},
"дата": {
"type": "string",
"format": "date"
},
"время": {
"type": "string",
"format": "time"
},
"дата_время": {
"type": "string",
"format": "date-time"
},
"uri": {
"type": "string",
"format": "uri"
},
"uuid": {
"type": "string",
"format": "uuid"
}
}
Композиция схем
allOf (И)
Данные должны соответствовать всем подсхемам:
{
"allOf": [
{
"type": "object",
"properties": {
"имя": {"type": "string"}
}
},
{
"properties": {
"возраст": {"type": "integer"}
}
}
]
}
anyOf (ИЛИ)
Данные должны соответствовать хотя бы одной подсхеме:
{
"контакт": {
"anyOf": [
{
"properties": {
"email": {"type": "string", "format": "email"}
},
"required": ["email"]
},
{
"properties": {
"телефон": {"type": "string"}
},
"required": ["телефон"]
}
]
}
}
oneOf (Исключающее ИЛИ)
Данные должны соответствовать ровно одной подсхеме:
{
"платеж": {
"oneOf": [
{
"properties": {
"тип": {"const": "карта"},
"номер_карты": {"type": "string"}
},
"required": ["тип", "номер_карты"]
},
{
"properties": {
"тип": {"const": "наличные"},
"сумма": {"type": "number"}
},
"required": ["тип", "сумма"]
}
]
}
}
not
Данные не должны соответствовать схеме:
{
"имя_пользователя": {
"type": "string",
"not": {
"enum": ["admin", "root", "superuser"]
}
}
}
Условная валидация
if-then-else
{
"type": "object",
"properties": {
"тип_доставки": {
"enum": ["курьер", "самовывоз"]
},
"адрес": {"type": "string"}
},
"if": {
"properties": {
"тип_доставки": {"const": "курьер"}
}
},
"then": {
"required": ["адрес"]
},
"else": {
"properties": {
"адрес": false
}
}
}
dependencies (зависимости)
Зависимости свойств:{
"type": "object",
"properties": {
"кредитная_карта": {"type": "string"},
"cvv": {"type": "string"}
},
"dependencies": {
"кредитная_карта": ["cvv"]
}
}
Схема зависимостей:
{
"type": "object",
"properties": {
"имя": {"type": "string"},
"кредитная_карта": {"type": "string"}
},
"dependentSchemas": {
"кредитная_карта": {
"properties": {
"платежный_адрес": {"type": "string"}
},
"required": ["платежный_адрес"]
}
}
}
Продвинутые возможности
$ref (Ссылки)
Внутренние ссылки:{
"$defs": {
"адрес": {
"type": "object",
"properties": {
"город": {"type": "string"},
"улица": {"type": "string"}
},
"required": ["город"]
}
},
"type": "object",
"properties": {
"домашний_адрес": {"$ref": "#/$defs/адрес"},
"рабочий_адрес": {"$ref": "#/$defs/адрес"}
}
}
Внешние ссылки:
{
"$ref": "https://example.com/schemas/user.json"
}
additionalProperties
Запрет дополнительных свойств:{
"type": "object",
"properties": {
"имя": {"type": "string"},
"возраст": {"type": "integer"}
},
"additionalProperties": false
}
Валидация дополнительных свойств:
{
"type": "object",
"properties": {
"известное_поле": {"type": "string"}
},
"additionalProperties": {
"type": "string"
}
}
propertyNames
{
"type": "object",
"propertyNames": {
"pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
}
}
minProperties, maxProperties
{
"type": "object",
"minProperties": 2,
"maxProperties": 10
}
Полные примеры схем
Схема пользователя
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://example.com/schemas/user.json",
"title": "Пользователь",
"description": "Схема для пользователя системы",
"type": "object",
"properties": {
"id": {
"type": "integer",
"description": "Уникальный идентификатор"
},
"имя_пользователя": {
"type": "string",
"minLength": 3,
"maxLength": 20,
"pattern": "^[a-zA-Z0-9_]+$",
"description": "Имя пользователя"
},
"email": {
"type": "string",
"format": "email",
"description": "Email адрес"
},
"пароль": {
"type": "string",
"minLength": 8,
"description": "Пароль (минимум 8 символов)"
},
"дата_рождения": {
"type": "string",
"format": "date",
"description": "Дата рождения"
},
"роль": {
"type": "string",
"enum": ["admin", "user", "moderator"],
"default": "user",
"description": "Роль пользователя"
},
"активен": {
"type": "boolean",
"default": true,
"description": "Статус активности"
},
"адрес": {
"type": "object",
"properties": {
"город": {"type": "string"},
"улица": {"type": "string"},
"индекс": {
"type": "string",
"pattern": "^\d{6}$"
}
},
"required": ["город"]
},
"теги": {
"type": "array",
"items": {"type": "string"},
"uniqueItems": true
}
},
"required": ["имя_пользователя", "email", "пароль"],
"additionalProperties": false
}
Схема API ответа
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "API Response",
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": ["success", "error"]
},
"code": {
"type": "integer",
"minimum": 100,
"maximum": 599
},
"message": {
"type": "string"
}
},
"required": ["status", "code"],
"if": {
"properties": {
"status": {"const": "success"}
}
},
"then": {
"properties": {
"data": {
"type": "object"
}
},
"required": ["data"]
},
"else": {
"properties": {
"error": {
"type": "object",
"properties": {
"type": {"type": "string"},
"details": {"type": "string"}
}
}
},
"required": ["error"]
}
}
Валидация с JSON Schema
JavaScript (ajv)
const Ajv = require('ajv');
const ajv = new Ajv();
const схема = {
type: 'object',
properties: {
имя: {type: 'string'},
возраст: {type: 'integer', minimum: 0}
},
required: ['имя']
};
const валидировать = ajv.compile(схема);
// Валидные данные
const данные1 = {имя: 'Иван', возраст: 30};
console.log(валидировать(данные1)); // true
// Невалидные данные
const данные2 = {возраст: 30};
console.log(валидировать(данные2)); // false
console.log(валидировать.errors);
Python (jsonschema)
import jsonschema
from jsonschema import validate
схема = {
"type": "object",
"properties": {
"имя": {"type": "string"},
"возраст": {"type": "integer", "minimum": 0}
},
"required": ["имя"]
}
# Валидные данные
данные1 = {"имя": "Иван", "возраст": 30}
try:
validate(instance=данные1, schema=схема)
print("✓ Данные валидны")
except jsonschema.exceptions.ValidationError as e:
print(f"✗ Ошибка: {e.message}")
# Невалидные данные
данные2 = {"возраст": 30}
try:
validate(instance=данные2, schema=схема)
except jsonschema.exceptions.ValidationError as e:
print(f"✗ Ошибка: {e.message}")
# Вывод: 'имя' is a required property
Java (everit-json-schema)
import org.everit.json.schema.Schema;
import org.everit.json.schema.loader.SchemaLoader;
import org.json.JSONObject;
import org.json.JSONTokener;
JSONObject schemaJson = new JSONObject(new JSONTokener(schemaString));
Schema schema = SchemaLoader.load(schemaJson);
JSONObject dataJson = new JSONObject(dataString);
schema.validate(dataJson); // Throws ValidationException if invalid
Генерация схем
Из примера данных
Python:import json
from genson import SchemaBuilder
# Примеры данных
примеры = [
{"имя": "Иван", "возраст": 30},
{"имя": "Мария", "возраст": 25, "email": "maria@example.com"}
]
# Генерация схемы
builder = SchemaBuilder()
for пример in примеры:
builder.add_object(пример)
схема = builder.to_schema()
print(json.dumps(схема, indent=2, ensure_ascii=False))
Из TypeScript типов
quicktype:quicktype -s schema data.json -o schema.json
Использование в API
OpenAPI/Swagger
paths:
/users:
post:
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/User'
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/UserResponse'
components:
schemas:
User:
type: object
properties:
name:
type: string
age:
type: integer
Express.js middleware
const Ajv = require('ajv');
const ajv = new Ajv();
function validateSchema(schema) {
const validate = ajv.compile(schema);
return (req, res, next) => {
const valid = validate(req.body);
if (!valid) {
return res.status(400).json({
error: 'Validation failed',
details: validate.errors
});
}
next();
};
}
// Использование
app.post('/users', validateSchema(userSchema), (req, res) => {
// req.body уже валидирован
});
Best Practices
1. Используйте $schema
{
"$schema": "http://json-schema.org/draft-07/schema#"
}
2. Добавляйте описания
{
"properties": {
"email": {
"type": "string",
"format": "email",
"description": "Email адрес пользователя для связи"
}
}
}
3. Используйте $defs для переиспользования
{
"$defs": {
"положительное_число": {
"type": "number",
"minimum": 0
}
},
"properties": {
"цена": {"$ref": "#/$defs/положительное_число"},
"количество": {"$ref": "#/$defs/положительное_число"}
}
}
4. Валидируйте саму схему
const Ajv = require('ajv');
const ajv = new Ajv();
const схемаВалидна = ajv.validateSchema(ваша_схема);
if (!схемаВалидна) {
console.error('Невалидная схема:', ajv.errors);
}
5. Используйте examples
{
"type": "string",
"format": "email",
"examples": [
"user@example.com",
"admin@company.ru"
]
}
Инструменты
Онлайн валидаторы
- jsonschemavalidator.net
- jsonschemalint.com
Редакторы
- VS Code с расширением JSON Schema
- JSONBuddy
Библиотеки
- JavaScript: ajv, jsonschema
- Python: jsonschema, fastjsonschema
- Java: everit-json-schema
- Go: gojsonschema
Заключение
JSON Schema — мощный инструмент для валидации и документирования JSON данных. Правильное использование схем повышает надежность приложений и упрощает разработку.
Ключевые преимущества:- Строгая валидация данных
- Самодокументируемые API
- Автогенерация кода
- Улучшенное тестирование
Начните использовать JSON Schema в ваших проектах для более надежной работы с данными!
Похожие статьи
Что такое JSON? Полное руководство для начинающих
Узнайте, что такое JSON, его синтаксис, типы данных и области применения. Полное руководство для начинающих по JavaScript Object Notation.
Файл JSON: Полное руководство по работе с .json файлами
Узнайте всё о файлах JSON: как их создавать, открывать, редактировать и использовать в различных приложениях и языках программирования.
Распространённые ошибки JSON и их решения
Полный справочник по распространённым ошибкам JSON: причины, примеры и способы исправления. Научитесь отлаживать и исправлять JSON.