Jackson: deserialización de un array de objetos en Java en 2025 — guía para profesionales

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: por qué todo desarrollador Java debería conocer este truco



Imagine: ha recibido un JSON del servidor, con decenas de objetos del mismo tipo. Clientes, productos, registros, da igual. Toma ObjectMapper, escribe readValue(json, MyClass[].class) y todo funciona. Pero un mes después, el código falla con un ClassCastException porque alguien reemplazó el array por un List. ¿Le suena?



La pregunta «How to use Jackson to deserialise an array of objects» en Stack Overflow ha acumulado decenas de miles de visitas. Y no es casualidad: la deserialización de un array de objetos en Java es una de esas tareas que parecen sencillas hasta que te enfrentas a los genéricos y la eliminación de tipos (Type Erasure). En 2025, Jackson sigue siendo el estándar de facto para trabajar con JSON, pero las mejores prácticas han cambiado. En este artículo, analizaremos no solo los enfoques básicos, sino también las técnicas modernas que le evitarán dolores de cabeza.



Enfoque básico: ¿array o lista?



La forma más sencilla es usar un array. Jackson entiende perfectamente que MyClass[].class es un array de objetos:



ObjectMapper mapper = new ObjectMapper();String json = "[{\\"id\\":1,\\"name\\":\\"Alice\\"},{\\"id\\":2,\\"name\\":\\"Bob\\"}]";MyClass[] array = mapper.readValue(json, MyClass[].class);


¿Funciona? Sí. Pero este enfoque tiene desventajas:

  • El array tiene un tamaño fijo, lo que es incómodo para datos dinámicos.
  • No tiene métodos de colecciones (stream(), filter(), remove()).
  • Es más difícil de ampliar si más adelante se necesita un List.


Por eso, en el 90% de los casos querrá obtener un List<MyClass>. Y aquí comienza lo interesante: la eliminación de tipos (Type Erasure) en Java. Si escribe:



List<MyClass> list = mapper.readValue(json, List.class); // warning: unchecked


El compilador se quejará y, en tiempo de ejecución, obtendrá un List<LinkedHashMap> en lugar de un List<MyClass>. Los genéricos se borran y Jackson no sabe a qué tipo mapear los elementos.



TypeReference: la forma correcta para List



La solución es usar TypeReference. Se trata de una clase interna anónima que conserva la información de los genéricos mediante reflexión:



List<MyClass> list = mapper.readValue(json, new TypeReference<List<MyClass>>() {});


Observe el {}: esto crea una clase anónima que captura el tipo. Jackson, a través de TypeFactory, entiende que debe deserializar un List de MyClass. Este enfoque es el estándar de oro en 2025.



¿Cuándo es incómodo TypeReference?

  • Si necesita formar el tipo dinámicamente (por ejemplo, desde una configuración).
  • Si necesita deserializar lo mismo muchas veces: crear una clase anónima cada vez puede ser costoso.


Para estos casos, existe una alternativa: CollectionType.



CollectionType: el poder de JavaType



Jackson proporciona TypeFactory para construir tipos complejos:



JavaType type = mapper.getTypeFactory()    .constructCollectionType(List.class, MyClass.class);List<MyClass> list = mapper.readValue(json, type);


Este método:

  • No crea clases anónimas (menos overhead).
  • Permite construir tipos dinámicamente: constructParametricType(Map.class, String.class, MyClass.class).
  • Es ideal para bibliotecas y frameworks donde los tipos no se conocen en tiempo de compilación.


Mejor práctica 2025: use TypeReference para casos simples y CollectionType cuando necesite flexibilidad o rendimiento.



Reader e InputStream: no olvide los recursos



Blogs

Book Recommendations