You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Spring WebClient调用POST接口返回Null问题求助

Spring WebClient调用POST接口返回Null的排查与解决

问题场景

调用https://countriesnow.space/api/v0.1/countries/population接口时,使用WebClient的bodyToMono(Object.class)获取返回值,结果得到Null,但预期应返回有效对象。相关代码如下:

WebClient配置:

final int size = 16 * 1024 * 1024;
    
final ExchangeStrategies strategies = ExchangeStrategies.builder()
        .codecs(codecs -> codecs.defaultCodecs().maxInMemorySize(size))
        .build();

@Bean
public WebClient webClient() { 
    return WebClient
            .builder()
            .exchangeStrategies(strategies)
            .build();
}

调用代码:

Object countryz = webClient.post()
        .uri(new URI("https://countriesnow.space/api/v0.1/countries/population"))
        .contentType(MediaType.APPLICATION_JSON)
        .accept(MediaType.APPLICATION_JSON)
        .body(BodyInserters.fromObject(country))
        .retrieve().bodyToMono(Object.class).block();

核心原因与解决办法

1. 直接反序列化为Object.class的问题

Object类无任何可映射字段,Jackson无法将JSON数据正确绑定到Object实例。即使接口返回有效JSON,这种方式也无法完成解析,最终大概率返回Null或无意义的空对象。

解决:定义对应DTO类接收响应
根据接口返回的JSON结构,创建匹配的DTO类,示例如下:

public class PopulationResponse {
    private boolean error;
    private String msg;
    private Data data;

    // 生成getter、setter、toString方法
    public static class Data {
        private String country;
        private List<PopulationEntry> populationCounts;

        // 生成getter、setter、toString方法
    }

    public static class PopulationEntry {
        private String year;
        private String value;

        // 生成getter、setter、toString方法
    }
}

修改调用代码,用DTO类反序列化:

PopulationResponse countryz = webClient.post()
        .uri("https://countriesnow.space/api/v0.1/countries/population")
        .contentType(MediaType.APPLICATION_JSON)
        .accept(MediaType.APPLICATION_JSON)
        .body(BodyInserters.fromValue(country))
        .retrieve()
        .bodyToMono(PopulationResponse.class)
        .block();

2. 过时的请求体插入方法

BodyInserters.fromObject()已被废弃,该方法在序列化请求体时可能存在兼容性问题,导致接口接收的参数不符合要求,进而返回空数据。

解决:改用fromValue()方法
将.body(BodyInserters.fromObject(country))替换为.body(BodyInserters.fromValue(country)),确保请求体正确序列化。

3. 未处理接口错误响应

当前代码未处理接口返回的错误状态码(如4xx、5xx),如果接口因参数错误返回200但内容为空,或直接返回错误状态码,都会导致最终得到Null。

解决:添加错误状态处理
在retrieve()后增加onStatus逻辑,捕获错误响应并输出详细信息:

PopulationResponse countryz = webClient.post()
        .uri("https://countriesnow.space/api/v0.1/countries/population")
        .contentType(MediaType.APPLICATION_JSON)
        .accept(MediaType.APPLICATION_JSON)
        .body(BodyInserters.fromValue(country))
        .retrieve()
        .onStatus(HttpStatus::isError, response -> {
            return response.bodyToMono(String.class)
                    .flatMap(errorBody -> Mono.error(new RuntimeException("接口返回错误: " + errorBody)));
        })
        .bodyToMono(PopulationResponse.class)
        .block();

4. 先验证接口实际返回内容

如果不确定接口返回的具体内容,可以先将响应体转为String,排查是否返回了预期数据:

String responseStr = webClient.post()
        .uri("https://countriesnow.space/api/v0.1/countries/population")
        .contentType(MediaType.APPLICATION_JSON)
        .accept(MediaType.APPLICATION_JSON)
        .body(BodyInserters.fromValue(country))
        .retrieve()
        .bodyToMono(String.class)
        .block();
System.out.println("接口原始返回: " + responseStr);

通过打印结果,可确认是接口返回空、参数错误还是结构不匹配导致的Null问题。


内容的提问来源于stack exchange,提问作者Srinivas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 13:31:04