← Вернуться к блогу

Понимание JSON Schema: Полное руководство по валидации данных

Исчерпывающее руководство по JSON Schema: создание схем, валидация данных, ключевые слова, примеры использования и лучшие практики для надежной работы с данными.

Big JSON Team16 мин чтенияadvanced
B

Big JSON Team

Technical Writer

Expert in JSON data manipulation, API development, and web technologies. Passionate about creating tools that make developers' lives easier.

16 мин чтения

# Понимание 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 в ваших проектах для более надежной работы с данными!

Share:

Похожие статьи

Read in English