使用RestTemplate调用外部API时处理多JSON响应映射问题
处理RestTemplate调用外部API时的不同响应结构问题
你当前直接使用restTemplate.getForObject()的写法,会在外部API返回错误结构JSON时因字段不匹配抛出序列化异常,无法正常映射到CountResponse。可以通过以下两种思路解决:
思路1:扩展DTO兼容两种响应结构
修改原有CountResponse,新增错误字段,让它能同时接收成功和错误响应:
@Data public class CountResponse { @JsonProperty(value = "PendingCount") private int pendingCount; @JsonProperty(value = "todayPendingCount") private int todayPendingCount; // 新增错误字段,匹配无数据时的响应结构 private String error; }
然后改用restTemplate.exchange()获取完整响应体,手动解析处理:
public ResponseEntity<CountResponse> count(@Validated @RequestBody CountRequest homeRequest) { String uri = "http://localhost:8089/abc?email=" + homeRequest.getEmail(); try { // 先获取原始响应字符串,避免直接序列化失败 ResponseEntity<String> responseEntity = restTemplate.exchange( uri, HttpMethod.GET, null, String.class ); ObjectMapper objectMapper = new ObjectMapper(); CountResponse result = objectMapper.readValue(responseEntity.getBody(), CountResponse.class); // 判断是否存在错误信息 if (result.getError() != null) { // 无数据时返回对应状态码,比如404 return ResponseEntity.status(HttpStatus.NOT_FOUND).body(result); } return ResponseEntity.ok(result); } catch (RestClientException | JsonProcessingException e) { // 处理调用或解析异常 CountResponse errorResult = new CountResponse(); errorResult.setError("调用外部API失败:" + e.getMessage()); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResult); } }
思路2:分别定义成功/错误DTO,动态解析
如果不想修改原有CountResponse,可以单独定义错误响应DTO:
@Data public class ErrorResponse { private String error; }
然后在控制器中优先尝试解析为成功DTO,失败则切换为错误DTO解析:
public ResponseEntity<?> count(@Validated @RequestBody CountRequest homeRequest) { String uri = "http://localhost:8089/abc?email=" + homeRequest.getEmail(); try { ResponseEntity<String> responseEntity = restTemplate.exchange( uri, HttpMethod.GET, null, String.class ); String responseBody = responseEntity.getBody(); ObjectMapper objectMapper = new ObjectMapper(); // 优先尝试解析成功响应 try { CountResponse countResponse = objectMapper.readValue(responseBody, CountResponse.class); return ResponseEntity.ok(countResponse); } catch (JsonProcessingException e) { // 解析失败,尝试解析错误响应 ErrorResponse errorResponse = objectMapper.readValue(responseBody, ErrorResponse.class); return ResponseEntity.status(HttpStatus.NOT_FOUND).body(errorResponse); } } catch (RestClientException e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("调用外部API失败:" + e.getMessage()); } }
关键注意点
- 不要直接用
getForObject():该方法会自动强制序列化到目标类,一旦结构不匹配就抛出异常,无法适配多结构响应场景。 - 用
exchange()拿原始响应体:手动控制序列化逻辑,才能灵活处理不同结构的JSON。 - 结合状态码判断:如果外部API在无数据时返回非2xx状态码(比如404),还可以用
ResponseErrorHandler统一处理;但如果返回2xx状态码,必须手动解析响应体判断内容。
内容的提问来源于stack exchange,提问作者vegeta
相关产品推荐
相关产品推荐

