Быстрый парсинг JSON в Java с новыми правилами безопасности в Fastjson2

24 июл 2026
4,397
603
31
2 недели

fastjson logo

Если вы работаете с Java больше пяти лет, название Fastjson наверняка вызывает у вас смешанные чувства. С одной стороны, библиотека действительно работала быстрее Jackson. С другой — регулярные уязвимости с десериализацией через AutoType превратили её использование в постоянный головную боль для специалистов по безопасности.

В команде Alibaba эти проблемы знали лучше других. Два года назад они фактически переписали библиотеку с нуля. Встречайте Fastjson2: переосмысленный движок для работы с JSON, где за основу взяли безопасность и производительность на современных версиях Java.

Как изменилась безопасность

Главный грех первой версии заключался в механизме AutoType. Он мог создавать произвольные Java-объекты из JSON-полезной нагрузки прямо во время парсинга. Злоумышленники регулярно находили способы обойти встроенный список заблокированных классов и вызывать RCE.

В Fastjson2 подход изменили кардинально. AutoType теперь выключен по умолчанию, а сканирование классов работает без жёстко зашитых белых списков. Появился режим SafeMode, который полностью запрещает автоматическую сборку произвольных объектов.

Реклама

Все флаги конфигурации по умолчанию перевели в состояние OFF. Библиотека больше не пытается угадывать типы там, где это может навредить.

Основные возможности

Разработчики ориентировались на современные версии JDK, начиная с Java 8 и заканчивая Java 21. Движок оптимизирован под использование Vector API, работу с типами Record и компактными строками.

Вот что выделяется при знакомстве с библиотекой:

  • Двухформатность. Поддержка обычного текстового JSON и бинарного протокола JSONB.
  • Быстрый выборочный парсинг через JSONPath без создания промежуточных Java-объектов.
  • Модули расширения для Kotlin с удобным DSL и полная поддержка Spring Framework версий 5 и 6.
  • Нативная сборка с GraalVM Native Image из коробки.

Быстрый старт в коде

Подключение библиотеки состоит из добавления одной зависимости в pom.xml:

<dependency>
    <groupId>com.alibaba.fastjson2</groupId>
    <artifactId>fastjson2</artifactId>
    <version>2.0.61</version>
</dependency>

Простой пример парсинга и сериализации выглядит знакомо:

import com.alibaba.fastjson2.JSON;

// Парсинг строки в объект
User user = JSON.parseObject("{\"name\":\"John\",\"age\":25}", User.class);

// Сериализация объекта в JSON
String json = JSON.toJSONString(user);

Если вы пишете на Kotlin, модуль fastjson2-kotlin предлагает лаконичные расширения. Код получается заметно cleaner за счёт функции-расширения to<T>():

import com.alibaba.fastjson2.*

val text = """{"id":1,"name":"John"}"""
val user = text.to<User>()

val jsonBytes = user.toJSONByteArray()

Бинарный формат JSONB для микросервисов

Текстовый JSON остаётся стандартом для REST API, но в межсервисном взаимодействии он теряет позиции из-за избыточного размера и затрат на конвертацию строк. Fastjson2 содержит встроенную реализацию бинарного формата JSONB.

JSONB кодирует типы данных и структуру в компактный набор байтов. Это дает существенную экономию трафика и ускоряет работу RPC-сервисов.

User user = new User(1, "John");

// Сериализация в байтовый массив JSONB
byte[] bytes = JSONB.toBytes(user);

// Сериализация с дополнительным сжатием структурированных данных
byte[] compactBytes = JSONB.toBytes(user, JSONWriter.Feature.BeanToArray);

// Обратный парсинг
User parsedUser = JSONB.parseObject(bytes, User.class);

Сжатие с опцией BeanToArray превращает объект в массив значений без повторения имён полей, что приближает эффективность формата к Protobuf или Kryo.

Выборочное чтение через JSONPath

Часто из огромного JSON-ответа микросервиса нужно забрать всего одно или два поля. Классические парсеры вроде Jackson сначала выстраивают в памяти полное дерево или создают объект со всеми полями, тратя ресурсы CPU и память.

Fastjson2 решает эту задачу с помощью реализации JSONPath стандарта SQL:2016. Он умеет извлекать данные напрямую из сырого байтового потока:

byte[] payload = fetchLargeJsonFromNetwork();

// Создаём и кэшируем путь
JSONPath path = JSONPath.of("$.data.user.id");

// Извлекаем значение напрямую из байтового массива
JSONReader reader = JSONReader.of(payload);
Object userId = path.extract(reader);

Такой трюк полезен в высоконагруженных пайплайнах обработки данных, где лишние аллокации объектов в JVM сразу приводят к частым паузам Garbage Collector.

Миграция с первой версии

Договориться о полной обратной совместимости при смене мажорной версии невозможно, но авторы постарались облегчить переход. Для проектов, завязанных на старый API, создали модуль совместимости:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>2.0.61</version>
</dependency>

Он использует старый groupId и пакеты com.alibaba.fastjson, но внутри работает на новом движке v2. Это дает возможность обновиться без переписывания сотен импортов в legacy-коде.

Однако при переходе нужно учитывать важные изменения:

  • Разбор циклических ссылок отключен по умолчанию.
  • Умное сопоставление полей (Smart Match) больше не работает из коробки.
  • Все опции сериализатора нужно включать явно через JSONWriter.Feature.

Fastjson2 получился взрослым и зрелым продуктом. Разработчики проделали работу над ошибками, избавились от опасных настроек по умолчанию и дали Java-экосистеме действительно быстрый инструмент.

Попробовать Fastjson2 однозначно стоит, если вы развиваете высоконагруженные сервисы, работаете со Spring 6 / GraalVM Native Image или ищете альтернативу тяжелым форматам сериализации в Kotlin-проектах.

🍪 Мы используем файлы cookie и сервис аналитики Яндекс.Метрика, чтобы сайт работал лучше. Продолжая пользоваться devtrends.ru, вы соглашаетесь с обработкой данных согласно Политике конфиденциальности.