使用Spring WebClient反序列化JSON数组时返回空数组的问题
排查Spring WebClient反序列化JSON数组返回空数组的问题
以下是逐步排查的方案:
1. 确认API实际返回的响应内容
首先排除API本身返回空数组的可能,通过WebClient获取原始响应字符串验证:
public Mono<String> getRawTaskHistoryResponse() { return this.webClient .get() .uri(Url) .headers(headers -> headers.setBasicAuth(config.getBasicAuth().getUsername(), config.getBasicAuth().getPassword())) .accept(MediaType.APPLICATION_JSON) .exchangeToMono(response -> { if (response.statusCode().is2xxSuccessful()) { return response.bodyToMono(String.class); } else { return response.createException().flatMap(Mono::error); } }); }
调用该方法,打印返回的字符串,确认是否包含预期的JSON数据。如果返回本身就是空数组,需要检查API的权限、参数或后端逻辑;如果返回有数据,继续下一步排查。
2. 单独测试Jackson反序列化能力
用Jackson手动反序列化原始JSON字符串,验证实体类映射是否正确:
// 假设rawJson是第一步获取到的原始响应字符串 ObjectMapper mapper = new ObjectMapper(); try { List<TaskHistoryView> taskList = mapper.readValue(rawJson, new TypeReference<List<TaskHistoryView>>() {}); System.out.println("反序列化结果数量:" + taskList.size()); } catch (JsonProcessingException e) { e.printStackTrace(); }
- 如果手动反序列化也得到空列表:检查实体类字段与JSON字段的匹配(比如大小写、拼写),或者JSON中存在特殊格式(如嵌套对象、数组嵌套)导致映射失败。
- 如果手动反序列化正常:问题出在WebClient的配置上,继续下一步。
3. 检查WebClient的Jackson配置
Spring WebClient默认使用上下文内的ObjectMapper,若该实例被自定义修改(如禁用自动映射、添加特殊模块),可能导致反序列化失败。可以为WebClient指定独立的ObjectMapper:
// 创建自定义ObjectMapper ObjectMapper customMapper = new ObjectMapper() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) .setSerializationInclusion(JsonInclude.Include.NON_NULL); // 配置WebClient使用自定义ObjectMapper WebClient customWebClient = WebClient.builder() .codecs(configurer -> { configurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(customMapper)); configurer.defaultCodecs().jackson2JsonEncoder(new Jackson2JsonEncoder(customMapper)); }) .build();
替换原WebClient实例后重新测试。
4. 修复实体类的Builder注解兼容性
使用@Builder时,Jackson可能无法正确实例化对象(尤其是低版本Jackson),可以添加@Jacksonized注解(Jackson 2.12+版本支持),或者暂时移除@Builder测试:
@Data @Builder @Jacksonized // 启用Jackson对Builder模式的支持 @NoArgsConstructor @AllArgsConstructor @JsonIgnoreProperties(ignoreUnknown = true) @JsonInclude(JsonInclude.Include.NON_NULL) public class TaskHistoryView { @JsonProperty("id") private String id; @JsonProperty("category") private String category; @JsonProperty("status") private String status; }
5. 验证响应的Content-Type
API返回的Content-Type如果不是标准的application/json(比如带字符集后缀application/json;charset=utf-8),可能导致WebClient的解码器无法识别。可以在获取响应时打印Content-Type,或者配置解码器忽略Content-Type限制:
WebClient webClient = WebClient.builder() .codecs(configurer -> { configurer.defaultCodecs().jackson2JsonDecoder( new Jackson2JsonDecoder(customMapper, MediaType.ALL) ); }) .build();
内容的提问来源于stack exchange,提问作者Noouhh
相关产品推荐
相关产品推荐

