Java ObjectMapper.readValue泛型反序列化返回LinkedHashMap的解决方法
问题原因
该类型转换问题由Java泛型擦除 + Jackson反序列化类型信息丢失共同导致:
- 代码中
new TypeReference<>(){}使用了钻石运算符,运行时泛型参数T会被擦除,Jackson无法获取要反序列化的目标类型,默认会将JSON对象反序列化为LinkedHashMap类型 - 传入的泛型实例
t本身未携带运行时类型信息,无法帮助Jackson确定目标反序列化类型
修复方案
方案1:传入Class类型参数(最适配当前场景)
直接把目标类的Class对象作为参数传入,Jackson可以直接通过Class获取完整类型信息,修改后的代码如下:
@Service public class PokemonManager implements PokemonService { // 建议将ObjectMapper提为类单例成员,避免每次方法调用重复创建,提升性能 private final ObjectMapper objectMapper = new ObjectMapper(); private HttpResponse<String> getStringHttpResponseByUrl(final String url) { HttpClient httpClient = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .GET().header("accept", "application/json") .uri(URI.create(url)).build(); HttpResponse<String> httpResponse = null; try { httpResponse = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); } catch (IOException | InterruptedException e) { e.printStackTrace(); } return httpResponse; } // 修改方法签名,传入Class<T>替代原实例参数 private <T> T getObjectResponse(Class<T> clazz, String url) { try { HttpResponse<String> response = getStringHttpResponseByUrl(url); // 补充空值判断避免空指针 if (response == null || response.body() == null) { return null; } return objectMapper.readValue(response.body(), clazz); } catch (JsonProcessingException e) { e.printStackTrace(); return null; } } private List<Pokemon> getAllPokemonsAsList() { final String POSTS_API_URL = "https://pokeapi.co/api/v2/pokemon?limit=10000"; // 调用时传入目标类的Class对象即可 PokeApiResponse pokeApiResponse = getObjectResponse(PokeApiResponse.class, POSTS_API_URL); System.out.println(pokeApiResponse); return pokeApiResponse.results; } @Override public List<Pokemon> getAll() { return getAllPokemonsAsList(); } }
方案2:传入TypeReference参数(适配嵌套泛型场景)
如果后续需要反序列化带泛型的复杂类型(比如直接反序列化为List<Pokemon>),可以直接把TypeReference作为参数传入:
// 方法定义 private <T> T getObjectResponse(TypeReference<T> typeReference, String url) { try { HttpResponse<String> response = getStringHttpResponseByUrl(url); if (response == null || response.body() == null) { return null; } return objectMapper.readValue(response.body(), typeReference); } catch (JsonProcessingException e) { e.printStackTrace(); return null; } } // 调用处显式指定TypeReference的泛型参数 private List<Pokemon> getAllPokemonsAsList() { final String POSTS_API_URL = "https://pokeapi.co/api/v2/pokemon?limit=10000"; PokeApiResponse pokeApiResponse = getObjectResponse(new TypeReference<PokeApiResponse>() {}, POSTS_API_URL); System.out.println(pokeApiResponse); return pokeApiResponse.results; }
额外优化建议:
getStringHttpResponseByUrl方法遇到异常时会返回null,建议补充更完善的异常抛出逻辑,避免上层调用出现无感知的空指针问题。
内容的提问来源于stack exchange,提问作者Fatih Enes
相关产品推荐
相关产品推荐

