1
0

Part 1: TypeReference, and what List.class actually produces

This commit is contained in:
2026-08-04 17:29:43 +00:00
parent 7f60c445ed
commit 97d54d33a1

View File

@@ -0,0 +1,54 @@
package com.ankurm.jackson3.part1objectmapper;
import tools.jackson.core.type.TypeReference;
import tools.jackson.databind.json.JsonMapper;
import java.util.List;
import java.util.Map;
/**
* Post: Jackson ObjectMapper Guide — https://ankurm.com/jackson-objectmapper-guide/
* Section: "Working with Collections and Generic Types"
*
* Why TypeReference is required, and what actually happens without it.
*
* Note the import: TypeReference lives in tools.jackson.core.type in Jackson 3.
*/
public class B03GenericCollections {
public record Article(Long articleId, String title) { }
public static void main(String[] args) {
JsonMapper mapper = JsonMapper.builder().build();
String jsonArray = "[{\"articleId\":1,\"title\":\"First\"},"
+ "{\"articleId\":2,\"title\":\"Second\"}]";
// CORRECT: TypeReference captures List<Article> through an anonymous subclass,
// so the parameterised type survives erasure and reaches Jackson at runtime.
List<Article> articles = mapper.readValue(jsonArray, new TypeReference<List<Article>>() { });
System.out.println("size : " + articles.size());
System.out.println("element class : " + articles.get(0).getClass().getSimpleName());
System.out.println("first title : " + articles.get(0).title());
// WRONG: List.class erases the element type. This COMPILES and does not throw
// here — the failure is deferred to the first time you treat an element as an
// Article, which is what makes it such an unpleasant bug.
@SuppressWarnings("rawtypes")
List raw = mapper.readValue(jsonArray, List.class);
System.out.println("raw element : " + raw.get(0).getClass().getSimpleName()
+ " <- not Article");
try {
Article boom = (Article) raw.get(0);
System.out.println("unreachable: " + boom);
} catch (ClassCastException e) {
System.out.println("cast fails : ClassCastException, as expected");
}
// A Map value type needs the same treatment.
String jsonObject = "{\"a\":{\"articleId\":9,\"title\":\"Nine\"}}";
Map<String, Article> byKey =
mapper.readValue(jsonObject, new TypeReference<Map<String, Article>>() { });
System.out.println("map value : " + byKey.get("a").title());
}
}