1. Бінарна серіалізація в Java
Бінарна серіалізація — це стандартний механізм Java, за якого об’єкт перетворюється на потік байтів максимально компактно й швидко. Для цього використовуються класи ObjectOutputStream і ObjectInputStream. Отриманий файл — набір байтів, який не призначений для читання людиною.
Її називають бінарною, оскільки все серіалізується в «сирому» вигляді: числа, рядки, масиви, навіть посилання між об’єктами перетворюються на байти. Це як щільно запакована валіза: ефективно й швидко, але без інструкції неочевидно, де що лежить.
Як це працює в Java?
Припустімо, у нас є клас User:
import java.io.Serializable;
public class User implements Serializable {
private String name;
private int age;
// Конструктор, гетери та сетери
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
}
Серіалізація у бінарний файл
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
User user = new User("Вася", 30);
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user.bin"))) {
out.writeObject(user);
System.out.println("Об’єкт User серіалізовано у файл user.bin");
} catch (Exception e) {
e.printStackTrace();
}
Десеріалізація з бінарного файлу
import java.io.FileInputStream;
import java.io.ObjectInputStream;
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("user.bin"))) {
User loadedUser = (User) in.readObject();
System.out.println("Прочитали з файлу: " + loadedUser.getName() + ", " + loadedUser.getAge());
} catch (Exception e) {
e.printStackTrace();
}
Увага: якщо відкрити файл user.bin у текстовому редакторі, ви побачите щось на кшталт: ¬í sr ... — це нормально, так і задумано!
Переваги бінарної серіалізації
- Компактність і швидкість. Збереження та читання виконуються максимально швидко, без зайвих «прикрашань».
- Зберігаються всі поля об’єкта, включно із вкладеними об’єктами (якщо вони також серіалізовані через Serializable).
- Просто використовувати для внутрішнього кешу або передавання між Java-програмами.
Недоліки
- Нечитабельність. Людина не зможе «підглянути» вміст і зрозуміти, що там.
- Жорстка прив’язаність до версії класу. Зміна структури (додавання/видалення полів) може «зламати» читання старих файлів.
- Проблеми сумісності між різними версіями Java і JVM.
- Не підходить для обміну з іншими мовами програмування.
- Безпека: десеріалізація даних із неперевірених джерел — прямий шлях до вразливостей.
2. Текстові формати серіалізації: JSON, XML та інші
Бінарна серіалізація добра для внутрішнього використання, але часто потрібно передавати дані між різними мовами (Java, JavaScript, Python) або зберігати їх у читабельному вигляді — зручно для конфігурацій, логів, API. Для цього використовують текстові формати: JSON, XML, YAML, CSV тощо.
JSON — найпопулярніший
JSON (JavaScript Object Notation) — компактний і читабельний формат. Приклад серіалізованого об’єкта User:
{
"name": "Вася",
"age": 30
}
У Java для роботи з JSON найчастіше використовують бібліотеки: Jackson (найпопулярніша), Gson, а також Moshi, JSON-B тощо.
XML — давній друг програміста
XML (Extensible Markup Language) — більш «багатослівний», але формальний і строгий.
<User>
<name>Вася</name>
<age>30</age>
</User>
Для XML у Java часто застосовують стандартну бібліотеку JAXB (або старішу XStream).
YAML, CSV та інші
- YAML — схожий на JSON, але більш лаконічний; частіше використовують для конфігурацій, ніж для серіалізації складних об’єктів.
- CSV — добрий для «пласких» таблиць, але погано підходить для вкладених структур.
- Інші формати є на будь-який смак, але в Java найчастіше використовують JSON і XML.
3. Порівняння форматів: коли що використовувати?
| Формат | Читабельність | Компактність | Швидкість | Сумісність | Коли використовувати |
|---|---|---|---|---|---|
| Бінарний | Ні | ++ | ++ | Лише Java | Внутрішній кеш, швидке збереження між JVM |
| JSON | Так | + | + | Будь-які мови | REST API, обмін із зовнішніми сервісами, конфіги |
| XML | Так | - | - | Будь-які мови | Інтеграція, суворі схеми, старі системи |
- Бінарний — обирайте для внутрішнього використання, коли не потрібен обмін із зовнішніми системами й важлива максимальна продуктивність.
- JSON — найкращий вибір для обміну з вебзастосунками, мобільними клієнтами та REST API, а також для зберігання налаштувань.
- XML — потрібен за суворих схем і інтеграції з «корпоративними» рішеннями.
Важливо! Бінарна серіалізація підходить лише для передавання даних між Java-програмами, і навіть у цьому випадку безпечніше використовувати її між програмами однієї версії. Текстові формати на кшталт JSON і XML універсальніші: вони підходять для обміну даними між різними мовами та платформами, роблячи інформацію читабельною й переносимою.
4. Практика: серіалізація в бінарний і текстовий формат
Бінарна серіалізація (ObjectOutputStream/ObjectInputStream)
Уже бачили вище, але повторимо для закріплення:
// Серіалізація
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user.bin"))) {
out.writeObject(user);
}
// Десеріалізація
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("user.bin"))) {
User loadedUser = (User) in.readObject();
}
Серіалізація в JSON за допомогою Jackson (коротко)
Щоб працювати з Jackson, потрібно додати його бібліотеки до проєкту. Згодом ми вивчимо Maven і Gradle, а поки що можна під’єднати JAR-файли вручну. Приклад залежності для Maven:
<!-- Maven -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.0</version>
</dependency>
Приклад серіалізації/десеріалізації:
import com.fasterxml.jackson.databind.ObjectMapper;
User user = new User("Вася", 30);
ObjectMapper mapper = new ObjectMapper();
try {
// Серіалізація в рядок
String json = mapper.writeValueAsString(user);
System.out.println(json); // {"name":"Вася","age":30}
// Серіалізація у файл
mapper.writeValue(new File("user.json"), user);
// Десеріалізація з рядка
User loadedUser = mapper.readValue(json, User.class);
// Десеріалізація з файлу
User loadedFromFile = mapper.readValue(new File("user.json"), User.class);
} catch (Exception e) {
e.printStackTrace();
}
JSON-файл можна відкрити в будь-якому текстовому редакторі, що робить дані легко читабельними та переносними між різними застосунками й мовами.
5. Коли який формат використовувати: практичні поради
- Внутрішнє кешування, тимчасові файли, швидкий запис/читання між Java-програмами: використовуйте стандартну бінарну серіалізацію. Але пам’ятайте про сумісність версій!
- Обмін із зовнішніми сервісами, зберігання налаштувань, інтеграція з фронтендом: використовуйте JSON (Jackson, Gson).
- Інтеграція з «корпоративними» системами, де потрібна сувора схема: XML (JAXB).
- Потрібно, щоб людина могла відкрити й прочитати файл: JSON або XML, але не бінарний формат.
6. Типові помилки під час роботи з форматами серіалізації
Помилка № 1: Намагаються серіалізувати об’єкт із несеріалізованими полями. Якщо у вашого класу є поле, яке не реалізує Serializable (наприклад, потік або з’єднання з БД), бінарна серіалізація спричинить помилку. Для JSON це не так критично, але з «нестандартними» типами також трапляються проблеми.
Помилка № 2: Відкривають бінарний файл у текстовому редакторі й лякаються. Це нормально! Бінарні файли не призначені для читання людиною.
Помилка № 3: Змінюють структуру класу, а старі бінарні файли перестають читатися. Бінарна серіалізація чутлива до змін структури класу — часто виникає InvalidClassException. У JSON/XML це менш критично: невідомі поля зазвичай ігноруються або отримують значення за замовчуванням.
Помилка № 4: Використовують бінарну серіалізацію для обміну із зовнішніми системами. Це не спрацює: бінарний формат розуміє лише Java, та й то за збігу версій.
Помилка № 5: Для JSON/XML забувають додати необхідні анотації. Деякі бібліотеки вимагають анотації на кшталт @JsonProperty, @XmlElement, інакше серіалізація/десеріалізація може працювати не так, як очікується.
Помилка № 6: Не перевіряють, що всі вкладені об’єкти можуть бути серіалізовані. Для бінарної серіалізації це часта проблема; для JSON — теж, якщо в моделі трапляються складні типи.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ