能否不使用ParameterizedTypeReference通过Spring RestTemplate获取JSON对象列表?
Spring Boot 3.1.1(基于Spring Framework 6)RestTemplate集合查询解决方案
问题背景
使用RestTemplate时,单个对象查询可通过getForObject直接获取响应体正常运行,但尝试用getForObject获取Collection<Ciencia>集合时,会因泛型类型擦除,导致Jackson将JSON数组反序列化为LinkedHashMap列表,进而抛出ClassCastException异常。
标准可行用法(使用ParameterizedTypeReference)
原本通过exchange方法配合ParameterizedTypeReference的写法可以正确获取泛型集合:
public ResponseEntity<Ciencia> findById(Integer id) { return restTemplate.getForEntity("/ciencias/uri/v1/ciencias/{id}", Ciencia.class, id); } public ResponseEntity<Collection<Ciencia>> findAll() { return restTemplate.exchange("/ciencias/uri/v1/ciencias", HttpMethod.GET, null, new ParameterizedTypeReference<Collection<Ciencia>>() {}); }
说明
- 两者均返回
ResponseEntity<T>类型,可获取请求头、状态码及响应体。
单个对象直接获取响应体的写法也可正常运行:
public Ciencia findById(Integer id) { return restTemplate.getForObject("/ciencias/uri/v1/ciencias/{id}", Ciencia.class, id); }
无需ParameterizedTypeReference的解决方案
1. 数组接收后转集合
利用数组的具体类型信息,避免泛型类型擦除问题:
public Collection<Ciencia> findAll() { Ciencia[] cienciasArray = restTemplate.getForObject("/ciencias/uri/v1/ciencias", Ciencia[].class); // 如需可变集合,可替换为 new ArrayList<>(Arrays.asList(cienciasArray)) return Arrays.asList(cienciasArray); }
原理:数组的类型是明确的Ciencia[],不存在泛型擦除,Jackson能直接将JSON元素反序列化为Ciencia对象,不会转为LinkedHashMap。
2. 自定义泛型响应包装类
如果后端接口返回的是包含集合的对象(而非直接返回数组),可定义包装类来承载响应:
// 泛型响应包装类 public class ListResponse<T> { private List<T> items; // getter 和 setter public List<T> getItems() { return items; } public void setItems(List<T> items) { this.items = items; } } // RestTemplate 查询方法 public Collection<Ciencia> findAll() { ListResponse<Ciencia> response = restTemplate.getForObject("/ciencias/uri/v1/ciencias", ListResponse.class); return response.getItems(); }
注意:此方式要求接口返回的JSON结构与包装类匹配,例如{"items": [/* Ciencia实例列表 */]}。
关于Spring Framework 5.x的说明
Spring Framework 5.x并未针对RestTemplate新增直接获取泛型集合的特殊方法,泛型类型擦除的限制依然存在,上述两种解决方案在Spring 5.x及6.x版本中均适用。
内容的提问来源于stack exchange,提问作者Manuel Jordan
相关产品推荐
相关产品推荐

