La gestión de valores nulos o cadenas vacías durante la conversión de JSON a objetos POJO es un aspecto crítico en el desarrollo con Java. A continuación, analizamos cómo interactúan las librerías Jackson y Fastjson ante diferentes escenarios de tipos de datos numéricos.
1. Procesamiento de tipos primitivos (int)
En este primer escenario, evaluamos el comportamiento cuando el campo es un tipo primitivo int, el cual no admite valores nulos de forma nativa en Java.
Escenario A: Sin valor inicial definido
@Data
public class UsuarioDTO {
private int edad;
}
Al ejecutar la deserialización con cadenas JSON que contienen valores nulos o vacíos:
@Test
public void analizarTiposPrimitivos() throws Exception {
ObjectMapper mapperJackson = new ObjectMapper();
String[] pruebas = {"{}", "{\"edad\": null}", "{\"edad\": \"\"}"};
for (String json : pruebas) {
System.out.println("Entrada JSON: " + json);
UsuarioDTO objJackson = mapperJackson.readValue(json, UsuarioDTO.class);
UsuarioDTO objFastjson = JSON.parseObject(json, UsuarioDTO.class);
System.out.println("Jackson -> " + objJackson);
System.out.println("Fastjson -> " + objFastjson);
}
}
Resultado: En ambos casos, el valor resultante es 0, ya que es el valor por defecto para un int no inicializado cuando el parser intenta asignar una ausencia de valor o un valor nulo.
Escenario B: Con valor inicial predeterminado
Si modificamos el DTO para que tenga un valor por defecto (por ejemplo, -1):
public class UsuarioDTO {
private int edad = -1;
}
Los resultados varían significativamente entre librerías:
- Entrada
{}: Ambas mantienen el valor-1porque el campo no existe en el JSON. - Entrada
{"edad": null}:- Jackson: Sobrescribe el campo con
0. - Fastjson: Mantiene el valor inicial
-1.
- Jackson: Sobrescribe el campo con
- Entrada
{"edad": ""}:- Jackson: Sobrescribe el campo con
0. - Fastjson: Mantiene el valor inicial
-1.
- Jackson: Sobrescribe el campo con
2. Procesamiento de tipos envoltorio (Integer)
El uso de la clase Integer permite que el campo almacene un valor null, lo cual cambia la lógica de asignación.
Escenario A: Sin valor inicial
public class UsuarioDTO {
private Integer edad;
}
Bajo las mismas entradas (null o ""), ambas librerías coinciden en asignar null al objeto final, manteniendo la consistencia con el tipo de dato.
Escenario B: Con valor inicial definido
public class UsuarioDTO {
private Integer edad = -1;
}
Cuando el DTO tiene un valor inicial pero el JSON intenta inyectar un nulo:
// Entrada: {"edad": null}
// Jackson -> UsuarioDTO(edad=null)
// Fastjson -> UsuarioDTO(edad=null)
A diferencia de los tipos primitivos, aquí ambas librerías priorzian el valor explícito del JSON (que es nulo) sobre el valor por defecto definido en la clase, resultando en un campo null para ambas herramientas.
Resumen de comportamiento
La diferencia técnica más notable reside en los tipos primitivos con valores predeterminados. Jackson tiende a forzar la conversión de un null JSON al valor predeterminado de Java para ese primitivo (0 para int), mientras que Fastjson opta por ignorar la asignación si el valor de entrada es nulo o vacío, permitiendo que prevalezca el valor inicial definido por el desarrollador en el DTO.