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.
| Ключ | Опис | Приклад |
|---|---|---|
|
Посилання на версію стандарту JSON Schema | |
|
Тип значення (object, array, string, number тощо) | |
|
Опис властивостей об’єкта | |
|
Масив обов’язкових полів | |
|
Опис типу елементів масиву | |
|
Перелік допустимих значень | |
, |
Обмеження для чисел | |
, |
Обмеження довжини рядків | |
|
Регулярний вираз для рядків | |
Наочно: приклад схеми для масиву людей
{
"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: реалізація бібліотеки відстає від стандарту. Стандарт розвивається, а бібліотеки — не завжди встигають. Деякі перевірки можуть бути відсутні або працювати інакше.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ