JavaRush /Курсы /C# SELF /Валидация JSON и <...

Валидация JSON и JSON Schema

C# SELF
47 уровень , 4 лекция
Открыта

1. Введение

Итак, вы уже умеете превращать объекты в JSON (и обратно). Но что делать, если на вход вашей программы попадает нечто… странное? Например, вы ожидали вот такой JSON:

{
  "id": 123,
  "name": "Alice",
  "email": "alice@example.com"
}

А получили:

{
  "name": 42,
  "id": "not a number"
}

Да, сериализаторы C# честно попробуют десериализовать этот беспредел, но зачастую это приводит к ошибкам в рантайме, потере данных или даже крошащемуся бизнесу. Перед тем как отправить данные дальше, сохранить их в базу или отправить по сети, проверьте, что данные валидны — иначе ваш код становится похожим на акробата без страховки.

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

2. Какие бывают способы валидации JSON?

В C# и .NET есть три главных подхода:

  • Валидация по собственному коду: вручную парсим объект, пишем проверки и бросаем исключения при ошибках.
  • Атрибуты валидации на моделях: например, [Required], [Range], [EmailAddress] из пространства имён System.ComponentModel.DataAnnotations.
  • Валидация с помощью JSON Schema — наш сегодняшний герой!

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

С помощью схем вы описываете:

  • Какие поля должны присутствовать.
  • Какие типы ожидаются (строка, массив, число, объект…).
  • Какие поля обязательные, а какие нет.
  • Диапазоны значений (например, возраст от 0 до 150).
  • Маски, длины, перечни значений и др.

Пример самой простой схемы

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

3. Основные элементы JSON Schema

Давайте разберёмся на примерах, что означают основные ключи в JSON Schema.

Ключ Описание Пример
$schema
Ссылка на версию стандарта JSON Schema
"https://json-schema.org/draft/2020-12/schema"
type
Тип значения (object, array, string, number и др.)
"type": "object"
properties
Описание свойств объекта
"properties": { ... }
required
Массив обязательных полей
"required": ["id"]
items
Описание типа элементов массива
"items": { ... }
enum
Перечень допустимых значений
"enum": ["A", "B"]
minimum
,
maximum
Ограничения для чисел
"minimum": 0
minLength
,
maxLength
Ограничения длины строк
"minLength": 3
pattern
Регулярное выражение для строк
"pattern": "^[a-zA-Z]+$"

Визуально: пример схемы для массива людей

{
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "id":    { "type": "integer" },
      "name":  { "type": "string", "minLength": 2, "maxLength": 50 },
      "email": { "type": "string", "format": "email" }
    },
    "required": ["id", "name"]
  }
}

4. Как провести валидацию JSON против схемы в C#

В .NET стандартной поддержки JSON Schema нет (по состоянию на .NET 9). На практике используют внешние библиотеки: NJsonSchema или Newtonsoft.Json.Schema (Json.NET Schema).

Установка пакета Newtonsoft.Json.Schema (Json.NET Schema)

Выполните в терминале (в папке проекта):

dotnet add package Newtonsoft.Json.Schema

Важно: Newtonsoft.Json.Schema — коммерческая библиотека (для некоммерческих целей доступна бесплатно). Для pet-проектов подходит идеально.

Пример проверки JSON на соответствие схеме

using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Schema;

string schemaJson = @"{
  'type': 'object',
  'properties': {
    'id':    { 'type': 'integer' },
    'name':  { 'type': 'string' },
    'email': { 'type': 'string', 'format': 'email' }
  },
  'required': ['id', 'name']
}";

// Представим, у нас есть такой JSON
string json = @"{
  'id': 123,
  'name': 'Alice',
  'email': 'alice@example.com'
}";

// Сначала парсим схему
JSchema schema = JSchema.Parse(schemaJson);

// Парсим сам JSON в JToken
JToken jsonObj = JToken.Parse(json);

// Проверяем, соответствует ли JSON схеме
bool valid = jsonObj.IsValid(schema, out IList<string> errors);

if (valid)
{
    Console.WriteLine("JSON валиден!");
}
else
{
    Console.WriteLine("JSON НЕ валиден!");
    foreach (var error in errors)
        Console.WriteLine(error);
}

Как использовать проверку JSON в приложении?

Обычно: сначала валидация (IsValid), затем десериализация (JsonConvert.DeserializeObject<T>) и только после — бизнес-логика. Это отсекает мусорные данные на ранней стадии.

if (jsonObj.IsValid(schema))
{
    // Всё хорошо, можно десериализовать
    var person = JsonConvert.DeserializeObject<Person>(json);
}
else
{
    // Прекратить обработку! Данные некорректны.
}

5. Применение JSON Schema в реальной жизни

Когда нужна валидация?

  • При получении данных по API (особенно от внешних систем и разных клиентов).
  • При миграции данных между микросервисами и базами.
  • При генерации UI-форм и автозаполнении, если форма строится на основе схемы.
  • На собеседованиях: вопрос «что если пришёл неправильный JSON?» встречается часто.

Интересный момент для любопытных

  • Проверка форматов: "format": "email", "date-time".
  • Составные правила: anyOf, oneOf, allOf.
  • Валидация вложенных объектов и массивов.
  • Расширения схем под свои нужды.

6. Крупный практический пример

Входные данные (список пользователей):

[
  { "id": 1, "name": "Alice", "email": "alice@example.com" },
  { "id": 2, "name": "Bob" },
  { "id": "что это?", "name": 123, "email": "not-an-email" }
]

Схема:

{
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "id":    { "type": "integer" },
      "name":  { "type": "string", "minLength": 2, "maxLength": 50 },
      "email": { "type": "string", "format": "email" }
    },
    "required": ["id", "name"]
  }
}

Проверка в .NET:

string jsonArray = @"[ ... ]"; // см. выше
string schemaJson = @"{ ... }"; // см. выше

JSchema schema = JSchema.Parse(schemaJson);
JToken arrayToken = JToken.Parse(jsonArray);

bool isValid = arrayToken.IsValid(schema, out IList<string> errs);
if (!isValid)
{
    foreach (var error in errs)
        Console.WriteLine(error);
    // Примеры сообщений:
    // "String 'что это?' is not a valid integer."
    // "Integer 123 is not a valid string."
    // "String 'not-an-email' is not a valid email address."
}

7. Типичные ошибки при работе с JSON-схемами

Ошибка №1: несоответствие схемы и актуальных данных. После изменения модели забывают обновить схему. Валидация либо пропускает ошибки, либо блокирует корректные данные.

Ошибка №2: несовпадение типов в схеме и в модели. Поле в модели сменило тип (например, id стал строкой), а в схеме остался integer — валидатор начнёт ругаться.

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

Ошибка №4: неверный формат данных. Поле типа string с email или датой выглядит «как строка», но может быть невалидным. Используйте format и/или дополнительные проверки.

Ошибка №5: реализация библиотеки отстаёт от стандарта. Стандарт развивается, а библиотеки — не всегда успевают. Некоторые проверки могут отсутствовать или работать иначе.

2
Задача
C# SELF, 47 уровень, 4 лекция
Недоступна
Массив объектов с JSON Schema
Массив объектов с JSON Schema
1
Опрос
Работа с JSON-данными, 47 уровень, 4 лекция
Недоступен
Работа с JSON-данными
Основы синтаксиса и структуры JSON
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ