使用响应式WebClient请求StackExchange API出现JSON解码异常如何修正
问题根源
- StackExchange接口返回的
items字段是数组结构,而非单个ItemsData对象,直接触发Jackson反序列化类型不匹配报错 - 实体类使用了大量不适用于JSON解析的注解,导致序列化/反序列化结构和接口实际返回结构完全不匹配
- 主类存在冗余的容器初始化逻辑,属于无意义重复代码
具体调整方案
1. 重构实体类
删除冗余类
直接删掉完全无用的ItemsData类,该类的结构和接口返回结构完全不匹配。
修改StackResponse类
将items字段声明为回答对象列表,匹配接口的数组结构:
@JsonIgnoreProperties(ignoreUnknown = true) @Data public class StackResponse { private List<AnswerItem> items; }
新增AnswerItem类
对应接口返回的items数组中的每个回答元素:
@JsonIgnoreProperties(ignoreUnknown = true) @Data public class AnswerItem { // 每个回答元素直接包含owner字段 private Owner owner; }
修改Owner类
删除所有会增加多余包装结构的注解,匹配接口返回的owner字段结构:
@Data @AllArgsConstructor @NoArgsConstructor @JsonIgnoreProperties(ignoreUnknown = true) public class Owner { @JsonProperty("user_id") private long userId; @JsonProperty("display_name") private String displayName; private String link; }
注意:需删除原Owner类上的@JsonTypeName、@JsonTypeInfo注解,以及所有类上的@JacksonXmlElementWrapper注解,这些是XML解析专用注解,不适用于JSON场景。
2. WebClient逻辑调整
原有WebClient的请求逻辑无需修改,若需要直接返回List<Owner>,可在方法内增加映射逻辑:
public Mono<List<Owner>> getOwners() { return this.webClient .get() .uri("https://api.stackexchange.com/2.2/answers?site=stackoverflow&page=1&pagesize=5&order=desc&sort=activity&filter=default") .accept(MediaType.APPLICATION_JSON) .retrieve() .bodyToMono(StackResponse.class) .map(stackResponse -> stackResponse.getItems().stream() .map(AnswerItem::getOwner) .collect(Collectors.toList())); }
若仍需要返回完整的StackResponse,保留原方法即可。
3. 主类冗余逻辑清理
删除重复初始化ApplicationContext的代码,Spring Boot启动时已自动初始化容器,可直接通过依赖注入获取StackResponseClient,修改后的主类示例:
@SpringBootApplication public class Application implements CommandLineRunner { @Autowired private StackResponseClient stackResponseClient; public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Override public void run(String... args) { // 测试获取完整StackResponse对象 StackResponse stackResponse = stackResponseClient.getOwners().block(); System.out.println(stackResponse); // 若已修改getOwners方法直接返回Owner列表,可使用以下测试代码 // List<Owner> owners = stackResponseClient.getOwners().block(); // System.out.println(owners); } }
结构匹配说明
修改后Jackson解析的结构会和接口返回结构完全对齐:
- 顶层对象包含
items数组 - 数组每个元素为回答对象,直接包含
owner字段 owner字段直接包含user_id、display_name、link属性,无多余嵌套包装
内容的提问来源于stack exchange,提问作者Dzikoŭski
相关产品推荐
相关产品推荐

