>_ DevTrendses

Idioma

Inicio

Lenguajes

Secciones

Frontend Backend Móvil DevOps AI / ML GameDev Blockchain Embebidos Seguridad
Java

Análisis rápido de JSON en Java con nuevas reglas de seguridad en Fastjson2

fastjson logo

Si has trabajado con Java durante más de cinco años, el nombre Fastjson probablemente te evoke sentimientos encontrados. Por un lado, la biblioteca era efectivamente más rápida que Jackson. Por otro lado, las vulnerabilidades regulares de deserialización a través de AutoType convirtieron su uso en un dolor de cabeza constante para los especialistas en seguridad.

El equipo de Alibaba conocía estos problemas mejor que nadie. Hace dos años, esencialmente reescribieron la biblioteca desde cero. Conoce a Fastjson2: un motor reimaginado para trabajar con JSON, donde la seguridad y el rendimiento en versiones modernas de Java fueron tomados como base.

Cómo ha cambiado la seguridad

El principal pecado de la primera versión fue el mecanismo AutoType. Podía crear objetos Java arbitrarios directamente desde el payload JSON durante el análisis. Los atacantes encontraban regularmente formas de evadir la lista incorporada de clases bloqueadas y provocar RCE.

En Fastjson2, el enfoque cambió dramáticamente. AutoType ahora está deshabilitado por defecto, y el escaneo de clases funciona sin listas blancas codificadas. Se introdujo un SafeMode, que prohíbe completamente el ensamblaje automático de objetos arbitrarios.

Todos los flags de configuración ahora están establecidos en OFF por defecto. La biblioteca ya no intenta adivinar tipos donde hacerlo podría causar daño.

Características principales

Los desarrolladores se enfocaron en versiones modernas de JDK, desde Java 8 hasta Java 21. El motor está optimizado para el uso de Vector API, tipos Record y cadenas compactas.

Esto es lo que destaca al conocer la biblioteca:

  • Soporte de formato dual. Tanto JSON de texto regular como el protocolo binario JSONB.
  • Análisis selectivo rápido a través de JSONPath sin crear objetos Java intermedios.
  • Módulos de extensión para Kotlin con un DSL conveniente y soporte completo de Spring Framework para las versiones 5 y 6.
  • Compilación nativa con GraalVM Native Image lista para usar.

Inicio rápido en código

Agregar la biblioteca implica incluir una única dependencia en pom.xml:

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

Un ejemplo simple de análisis y serialización se ve familiar:

import com.alibaba.fastjson2.JSON;

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

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

Si escribes en Kotlin, el módulo fastjson2-kotlin ofrece extensiones concisas. El código resulta notablemente más limpio gracias a la función de extensión to<T>():

import com.alibaba.fastjson2.*

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

val jsonBytes = user.toJSONByteArray()

Formato binario JSONB para microservicios

El JSON de texto sigue siendo el estándar para APIs REST, pero en la comunicación entre servicios pierde terreno debido al tamaño excesivo y la sobrecarga de conversión de cadenas. Fastjson2 contiene una implementación incorporada del formato binario JSONB.

JSONB codifica tipos de datos y estructura en un conjunto compacto de bytes. Esto proporciona ahorros sustanciales de tráfico y acelera los servicios 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);

La compresión con la opción BeanToArray transforma un objeto en un array de valores sin repetir nombres de campos, acercando la eficiencia del formato a Protobuf o Kryo.

Lectura selectiva a través de JSONPath

A menudo, de una enorme respuesta JSON de un microservicio, solo necesitas extraer uno o dos campos. Los analizadores clásicos como Jackson primero construyen un árbol completo en memoria o crean un objeto con todos los campos, consumiendo recursos de CPU y memoria.

Fastjson2 resuelve este problema con una implementación del estándar SQL:2016 JSONPath. Puede extraer datos directamente desde un flujo de bytes sin procesar:

byte[] payload = fetchLargeJsonFromNetwork();

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

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

Este truco es útil en pipelines de procesamiento de datos de alta carga donde las asignaciones de objetos innecesarios en la JVM inmediatamente conducen a pausas frecuentes del Garbage Collector.

Migrando desde la primera versión

Lograr compatibilidad total hacia atrás al cambiar las versiones principales es imposible, pero los autores intentaron facilitar la transición. Se creó un módulo de compatibilidad para proyectos que dependen de la API antigua:

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

Utiliza los antiguos paquetes groupId y com.alibaba.fastjson, pero internamente funciona con el nuevo motor v2. Esto hace posible actualizar sin reescribir cientos de importaciones en código heredado.

Sin embargo, al migrar, necesitas tener en cuenta cambios importantes:

  • El análisis de referencias cíclicas está deshabilitado por defecto.
  • La coincidencia inteligente de campos ya no funciona fuera de la caja.
  • Todas las opciones del serializador deben habilitarse explícitamente a través de JSONWriter.Feature.

Fastjson2 resultó ser un producto maduro y sólido. Los desarrolladores aprendieron de los errores pasados, eliminaron configuraciones peligrosas por defecto y le dieron al ecosistema Java una herramienta verdaderamente rápida.

Definitivamente prueba Fastjson2 si estás desarrollando servicios de alta carga, trabajando con Spring 6 / GraalVM Native Image, o buscando una alternativa a formatos de serialización pesados en proyectos Kotlin.

Proyectos relacionados