1. Навіщо потрібна валідація JSON
Уявімо: ви написали клас User і очікуєте, що на вхід завжди приходитиме ось такий JSON:
{
"id": 42,
"name": "Alice",
"email": "alice@example.com"
}
Але раптом вам прилітає ось це:
{
"id": "сорок два",
"name": 123,
"email": null,
"admin": true
}
Або взагалі:
{
"username": "Alice"
}
У кращому разі Jackson або Gson викинуть виняток під час спроби десеріалізації. У гіршому — мовчки встановлять полям значення за замовчуванням, і ваш бізнес‑код почне працювати некоректно. А якщо це конфіг для вашого сервісу — можна нарватися на веселі баги, які потім шукає вся команда.
Валідація JSON — це процес перевірки, що структура, типи та значення даних у JSON відповідають визначеним правилам (схемі). Це як паспортний контроль для даних: не пройшов — на борт не пускаємо!
2. JSON Schema: що це і як виглядає
У світі JSON є офіційний стандарт опису структури даних — JSON Schema. Це такий «чек‑ліст», за яким можна перевірити, що JSON підходить під вимоги вашої програми.
JSON Schema — це теж JSON, тільки зі спеціальними ключами: type, properties, required і так далі.
Приклад найпростішої схеми
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" },
"email": { "type": "string", "format": "email" }
},
"required": ["id", "name"]
}
Що тут відбувається:
- Очікується об’єкт (type: "object").
- У об’єкті можуть бути поля "id", "name", "email" (описуються в properties).
- "id" — обов’язково ціле число (type: "integer").
- "name" — обов’язково рядок (type: "string").
- "email" — рядок, який виглядає як email (ключ format зі значенням "email").
- required вказує перелік обов’язкових полів: "id" і "name".
Якщо в JSON бракуватиме "id" або "name", чи їхній тип буде іншим — JSON не пройде валідацію.
Коротко про можливості JSON Schema
- Задання типу (type: "string", "integer", "array", "object", "boolean", "null").
- Опис вкладених об’єктів і масивів (properties, items).
- Обов’язкові та необов’язкові поля (required).
- Перевірка довжини рядків, діапазону чисел (minLength, maximum тощо).
- Перевірка формату (format: "email", "date", "uri" тощо).
- Перелічення (enum: список допустимих значень).
- Регулярні вирази для рядків (pattern).
- Складні умови: anyOf, oneOf, allOf (для просунутих випадків).
3. Валідація JSON у Java: огляд бібліотек
До стандартної бібліотеки Java валідація JSON за схемою не входить. Але є популярні сторонні бібліотеки. Ось найвідоміші:
- everit-org/json-schema — проста, безкоштовна й популярна.
- networknt/json-schema-validator — швидка, підтримує останні стандарти.
- Jackson-module-jsonSchema — розширення для Jackson (але не підтримує повноцінну валідацію).
- Justify, Java JSON Tools — є й інші, але вони трапляються рідше.
У цій лекції ми розглянемо everit-org/json-schema — вона проста для новачків, добре задокументована і не вимагає танців з бубном.
Встановлення everit-org/json-schema
Додайте залежність до вашого pom.xml (Maven):
<dependency>
<groupId>org.everit.json</groupId>
<artifactId>org.everit.json.schema</artifactId>
<version>1.14.2</version>
</dependency>
Або через Gradle:
implementation 'org.everit.json:org.everit.json.schema:1.14.2'
4. Приклад: валідація JSON за схемою (покроково)
Спробуймо провалідувати JSON на практиці. Для цього нам знадобляться сама схема, JSON і трохи коду.
Приклад схеми (user-schema.json):
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": { "type": "integer" },
"name": { "type": "string", "minLength": 2, "maxLength": 30 },
"email": { "type": "string", "format": "email" }
},
"required": ["id", "name"]
}
Приклад валідного JSON (user.json):
{
"id": 1,
"name": "Alice",
"email": "alice@example.com"
}
Приклад невалідного JSON:
{
"id": "один",
"name": "",
"email": "not-an-email"
}
Код для валідації
import org.everit.json.schema.Schema;
import org.everit.json.schema.loader.SchemaLoader;
import org.json.JSONObject;
import org.json.JSONException;
import org.json.JSONTokener;
import org.everit.json.schema.ValidationException;
import java.nio.file.Files;
import java.nio.file.Paths;
public class JsonValidationExample {
public static void main(String[] args) throws Exception {
// Завантаження схеми з файлу
String schemaString = new String(Files.readAllBytes(Paths.get("user-schema.json")));
JSONObject rawSchema = new JSONObject(new JSONTokener(schemaString));
Schema schema = SchemaLoader.load(rawSchema);
// Завантаження JSON для перевірки
String jsonString = new String(Files.readAllBytes(Paths.get("user.json")));
JSONObject json = new JSONObject(new JSONTokener(jsonString));
// Валідація
try {
schema.validate(json); // Якщо все гаразд — нічого не відбудеться
System.out.println("JSON валідний!");
} catch (ValidationException e) {
System.out.println("JSON НЕ валідний!");
for (String msg : e.getAllMessages()) {
System.out.println("Помилка: " + msg);
}
}
}
}
Коментарі до коду:
- Використовується клас Schema і завантажувач SchemaLoader.load(...).
- Метод schema.validate(json) викидає виняток у разі невідповідності схемі.
- У блоці catch можна отримати всі помилки через getAllMessages().
Як це інтегрувати в застосунок?
Зазвичай схема зберігається в ресурсах (наприклад, у папці resources). Ви валідуєте JSON до десеріалізації в Java‑об’єкт. Якщо все гаразд — десеріалізуєте й працюєте далі.
5. Обробка помилок валідації
Коли JSON не проходить перевірку, бібліотека викидає виняток ValidationException. У повідомленні міститься список помилок: що саме не відповідає схемі.
Приклад виводу помилок
Для невалідного JSON, наведеного вище, вивід буде приблизно таким:
JSON НЕ валідний!
Помилка: #: required key [id] not found
Помилка: #/name: expected minLength: 2, actual: 0
Помилка: #/email: String [not-an-email] is invalid against requested format [email]
Помилка: #/id: expected type: Integer, found: String
Як інтерпретувати помилки:
- required key [id] not found — відсутнє обов’язкове поле.
- expected minLength: 2, actual: 0 — рядок занадто короткий.
- String [...] is invalid against requested format [email] — некоректний email.
- expected type: Integer, found: String — тип не збігається.
Важливо! Повідомлення можуть бути англійською, але вони цілком зрозумілі.
Як показати помилки користувачеві?
Ви можете зібрати помилки у список і віддати користувачеві, наприклад, у REST API або GUI. Це дозволить швидко зрозуміти, що саме не так із вхідними даними.
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": 30 },
"email": { "type": "string", "format": "email" }
},
"required": ["id", "name"]
}
}
Валідація працює так само, тільки замість об’єкта як JSON передаємо масив. Помилки міститимуть індекси елементів, де щось не так (наприклад, [#/2/id]).
7. Типові помилки під час валідації JSON
Помилка № 1: Невідповідність типів даних. Дуже часто приходить рядок замість числа ("id": "123"), а схема чекає integer. Валідацію не пройде. Якщо ви не контролюєте джерело даних — або виправте схему, або конвертуйте дані заздалегідь.
Помилка № 2: Відсутність обов’язкових полів. Якщо в схемі вказано, що поле обов’язкове ("required": ["id","name"]), а в JSON його немає — отримаєте помилку. Іноді це буває неочікувано: фронтенд забув надіслати поле або API змінилося.
Помилка № 3: Зайві поля в JSON. За замовчуванням JSON Schema дозволяє зайві поля. Якщо ви хочете сувору схему, не забудьте додати "additionalProperties": false. Без цього в JSON можуть бути будь‑які сторонні поля.
Помилка № 4: Неправильна версія схеми або синтаксис. Якщо ви використовуєте ключі, яких немає у вашій версії схеми, або робите друкарські помилки, валідатор не зможе завантажити схему. Перевіряйте схему на https://www.jsonschemavalidator.net/ або аналогічних сервісах.
Помилка № 5: Погана обробка помилок. Якщо просто ловити перший виняток і не показувати користувачеві подробиці, буде складно зрозуміти, що саме не так із JSON. Використовуйте getAllMessages() для виведення всіх помилок.
Помилка № 6: Надто суворі формати. Перевірка "format": "email" або "date" буває доволі «поверхневою». Якщо вам потрібна сувора валідація, використовуйте додаткові перевірки в коді.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ