JavaRush /Курси /JAVA 25 SELF /Валідація JSON: JSON Schema, помилки валідації

Валідація JSON: JSON Schema, помилки валідації

JAVA 25 SELF
Рівень 46 , Лекція 4
Відкрита

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" буває доволі «поверхневою». Якщо вам потрібна сувора валідація, використовуйте додаткові перевірки в коді.

1
Опитування
Серіалізація JSON, рівень 46, лекція 4
Недоступний
Серіалізація JSON
Серіалізація JSON
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ