Java Serialization vs JSON: когда что использовать?
Стандартная Java-сериализация (Serializable) и JSON-сериализация (Jackson, Gson) решают схожую задачу — преобразование объектов в переносимый формат, — но кардинально различаются по безопасности, совместимости и области применения.
Сравнительная таблица
| Критерий | Java Serialization | JSON (Jackson и др.) | Бинарные форматы (Protobuf, Avro) |
|---|---|---|---|
| Читаемость | Нет (бинарный) | Да (текстовый) | Нет (бинарный) |
| Кросс-языковость | Только Java | Любой язык | Любой язык (кодогенерация) |
| Производительность | Средняя | Средняя | Высокая |
| Размер данных | Большой (метаданные) | Средний | Маленький |
| Эволюция схемы | Хрупкая (serialVersionUID) |
Гибкая (новые поля игнорируются) | Встроенная поддержка |
| Безопасность | Опасная (атаки десериализации) | Безопасная (при правильной настройке) | Безопасная |
| REST API | Не применимо | Стандарт | Используется в gRPC |
Почему Java Serialization опасна
Десериализация данных из непроверенного источника может привести к Remote Code Execution (RCE). Атака основана на «gadget chains» — цепочках вызовов в библиотеках (Apache Commons Collections, Spring и др.), которые при десериализации выполняют произвольный код.
Пример
// ОПАСНО: десериализация из непроверенного источника
ObjectInputStream ois = new ObjectInputStream(untrustedInput);
Object obj = ois.readObject(); // Злоумышленник может выполнить произвольный код
С Java 9+ можно использовать ObjectInputFilter для ограничения допустимых классов, но это не решает проблему полностью:
Пример
ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(
"com.myapp.**;!*" // Разрешить только свои классы
);
ois.setObjectInputFilter(filter);
Когда что выбрать
| Формат | Когда использовать |
|---|---|
| JSON | REST API, конфигурации, межсервисное взаимодействие по HTTP, NoSQL (MongoDB), логирование |
| Protobuf / gRPC | Высоконагруженное межсервисное взаимодействие, когда важна производительность и размер |
| Avro | Потоковая обработка (Kafka, Spark), event-driven архитектура с эволюцией схем |
| Java Serialization | Практически не используется в новых проектах. Встречается в legacy, RMI |
Частые ошибки
- Использование Java Serialization для межсервисного обмена — невозможно прочитать на стороне, написанной не на Java
- Десериализация Java-объектов из непроверенных источников без фильтров — критическая уязвимость (CWE-502)
- Хранение сериализованных Java-объектов в БД — невозможно мигрировать при изменении классов
- Предположение, что JSON безопасен «автоматически» — полиморфная десериализация в Jackson (
@JsonTypeInfo) тоже может быть вектором атаки
На собеседовании: главный тезис — Java Serialization не рекомендуется для новых проектов (позиция Oracle и OWASP). JSON — стандарт для API. Protobuf/Avro — для высоконагруженных внутренних коммуникаций. Упомяните проблему безопасности (gadget chains) — это покажет глубокое понимание.