RestTemplate exchange获取List<LdapUserDto>反序列化失败求助
问题与解决方案
问题详情
调用POST接口时,使用RestTemplate尝试接收List<LdapUserDto>类型响应,触发JSON反序列化错误,提示无法从Object类型转为ArrayList。
请求代码
String url = "http://localhost:8080/admin/user/find/all/email"+"?email={email}"; ResponseEntity<List<LdapUserDto>> responseEntity = restTemplate.exchange( url, HttpMethod.POST, null, new ParameterizedTypeReference<List<LdapUserDto>>() {}, email);
DTO定义
@Getter @Setter @NoArgsConstructor @AllArgsConstructor public class LdapUserDto { @JsonProperty("id") private String id; @JsonProperty("email") private String email; @JsonProperty("fullName") private String fullName; }
预期响应格式
[ { "id": "7264a0e5", "email": "Admin@telecom.mu", "fullName": "Administrator" }, { "id": "0eccd314", "email": "ABC.John@telecom.mu", "fullName": "ABC John" } ]
错误日志
2022-08-16 01:06:48.407 DEBUG [admin,917e5c4b9e42604c,917e5c4b9e42604c] 15716 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Failed to complete request: org.springframework.web.client.RestClientException: Error while extracting response for type [java.util.List<com.cloudportal.admin.dto.response.user.LdapUserDto>] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.util.ArrayList<com.cloudportal.admin.dto.response.user.LdapUserDto>` from Object value (token `JsonToken.START_OBJECT`); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.util.ArrayList<com.cloudportal.admin.dto.response.user.LdapUserDto>` from Object value (token `JsonToken.START_OBJECT`) at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column: 1] 2022-08-16 01:06:48.415 ERROR [admin,917e5c4b9e42604c,917e5c4b9e42604c] 15716 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.client.RestClientException: Error while extracting response for type [java.util.List<com.cloudportal.admin.dto.response.user.LdapUserDto>] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.util.ArrayList<com.cloudportal.admin.dto.response.user.LdapUserDto>` from Object value (token `JsonToken.START_OBJECT`); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.util.ArrayList<com.cloudportal.admin.dto.response.user.LdapUserDto>` from Object value (token `JsonToken.START_OBJECT`) at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column: 1]] with root cause com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.util.ArrayList<com.cloudportal.admin.dto.response.user.LdapUserDto>` from Object value (token `JsonToken.START_OBJECT`) at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column: 1]
解决思路
错误本质是接口实际返回的JSON是对象({}),而非你预期的数组([]),导致Jackson无法完成反序列化。可按以下方向排查修复:
1. 确认接口真实返回格式
先用Postman/curl调用目标接口,查看实际返回的JSON结构:
- 如果返回的是包裹数组的对象(例:
{"users": [{},{}]}),需新增响应包装类适配:
再修改RestTemplate调用代码:@Getter @Setter public class LdapUserListResponse { @JsonProperty("users") // 对应实际返回的数组字段名 private List<LdapUserDto> users; }ResponseEntity<LdapUserListResponse> responseEntity = restTemplate.exchange( url, HttpMethod.POST, null, new ParameterizedTypeReference<LdapUserListResponse>() {}, email); List<LdapUserDto> userList = responseEntity.getBody().getUsers();
2. 调整请求参数传递方式
你当前用POST请求但将参数放在URL查询串中,部分接口要求POST参数放在请求体:
HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity<String> requestEntity = new HttpEntity<>(email, headers); ResponseEntity<List<LdapUserDto>> responseEntity = restTemplate.exchange( "http://localhost:8080/admin/user/find/all/email", HttpMethod.POST, requestEntity, new ParameterizedTypeReference<List<LdapUserDto>>() {});
3. 配置RestTemplate兼容格式
若接口可能返回单个对象或数组,可配置Jackson支持单值转数组:
@Bean public RestTemplate restTemplate() { RestTemplate restTemplate = new RestTemplate(); MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); ObjectMapper mapper = new ObjectMapper(); // 允许将单个对象反序列化为数组 mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); converter.setObjectMapper(mapper); restTemplate.getMessageConverters().add(converter); return restTemplate; }
内容的提问来源于stack exchange,提问作者SjAnupa
相关产品推荐
相关产品推荐

