SpringBoot用RestTemplate调用服务时RestResponse泛型data转Dto失败问题
问题原因
Java泛型存在类型擦除机制,你调用postForEntity时传入RestResponse.class作为响应类型,运行时无法获取到RestResponse的泛型参数SomeDto,负责反序列化的Jackson库无法识别data字段的目标类型,只能默认将JSON对象反序列化为LinkedHashMap。
注意:你的
RestResponse类需要为所有私有字段提供public的getter、setter方法,否则会导致反序列化失败。
解决方案
方案1:使用ParameterizedTypeReference传递泛型信息(推荐)
Spring提供了ParameterizedTypeReference类用于保留泛型类型信息,配合RestTemplate.exchange方法使用即可正确反序列化:
// 构造带泛型信息的类型引用 ParameterizedTypeReference<RestResponse<SomeDto>> typeRef = new ParameterizedTypeReference<RestResponse<SomeDto>>() {}; // 使用exchange方法发起POST请求 ResponseEntity<RestResponse<SomeDto>> result = new RestTemplate().exchange( uri, HttpMethod.POST, new HttpEntity<>(requestBody), typeRef ); // 此时result.getBody().getData()就是已序列化好的SomeDto对象
方案2:手动转换LinkedHashMap(快速兼容现有代码)
如果不想修改原有调用逻辑,可以拿到结果后用Jackson的ObjectMapper手动转换data字段:
ResponseEntity<RestResponse> result = new RestTemplate().postForEntity(uri, requestBody, RestResponse.class); RestResponse responseBody = result.getBody(); // 手动转换data字段 ObjectMapper objectMapper = new ObjectMapper(); SomeDto someDto = objectMapper.convertValue(responseBody.getData(), SomeDto.class);
方案3:封装通用RestTemplate工具类(适合多场景复用)
如果项目中大量使用RestResponse作为返回结构,可以封装通用工具类简化调用:
public <T> RestResponse<T> postForRestResponse(String uri, Object requestBody, Class<T> dataClass) { ParameterizedTypeReference<RestResponse<T>> typeRef = new ParameterizedTypeReference<RestResponse<T>>() {}; ResponseEntity<RestResponse<T>> response = restTemplate.exchange( uri, HttpMethod.POST, new HttpEntity<>(requestBody), typeRef ); return response.getBody(); }
调用时只需传入data对应的Class即可:
RestResponse<SomeDto> response = restTemplateUtil.postForRestResponse(uri, requestBody, SomeDto.class);
内容的提问来源于stack exchange,提问作者MARAZ
相关产品推荐
相关产品推荐

