JavaRush /Курсы /JAVA 25 SELF /Стандартные форматы сериализации: бинарный, текстовый

Стандартные форматы сериализации: бинарный, текстовый

JAVA 25 SELF
42 уровень , 2 лекция
Открыта

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 — лучший выбор для обмена с web-приложениями, мобильными клиентами и 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 — тоже, если в модели встречаются сложные типы.

1
Задача
JAVA 25 SELF, 42 уровень, 2 лекция
Недоступна
Сериализация объекта в бинарный файл
Сериализация объекта в бинарный файл
1
Задача
JAVA 25 SELF, 42 уровень, 2 лекция
Недоступна
Десериализация объекта из бинарного файла
Десериализация объекта из бинарного файла
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ