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

Spring Boot中WebClient.block()获取大JSON被截断缺失的原因是什么?

核心疑问解答

block()的作用仅为阻塞当前线程等待WebClient的异步响应读取流程结束,并不会控制响应内容的读取长度。你遇到的固定长度截断是Spring WebClient内置解码器的默认最大内存缓冲区限制导致:Spring Boot 2.4.x版本对应的Spring Webflux默认单请求最大内存缓冲区为4MB(和你遇到的4193150字符阈值完全吻合,UTF-8编码下1个英文字符占1字节,4MB约等于4194304字节),响应超过该阈值后,解码器会直接截断不再读取后续内容,因此你拿到的JSON字符串本身就是不完整的,和是否调用block()没有关系。

代码存在的其他问题
  • 冗余编码转换:你将响应转为String后又调用getBytes("UTF-8")再重新转回UTF-8字符串,属于完全无效的操作,不会解决任何问题,反而会额外占用内存。
  • ObjectMapper配置顺序错误:你先执行readValue解析JSON,再配置FAIL_ON_UNKNOWN_PROPERTIES=false,该配置对前面的解析操作完全不生效,相当于无用代码。
  • 字符串取值逻辑错误:调用nameNode.toString()、mainNode.get("id").toString()会把JSON字符串值包裹上双引号,你后续用replaceAll("\"", "")删除引号属于多此一举,直接调用asText()方法就能拿到原生字符串值。
  • 重复创建ObjectMapper:每次方法调用都新建ObjectMapper实例是严重的性能浪费,ObjectMapper是线程安全的,完全可以全局初始化复用。
修复方案
  1. 调整WebClient最大内存缓冲区限制,有两种可选方式:
    • 全局配置:在application.properties/application.yml中添加配置 spring.codec.max-in-memory-size=10MB(可根据实际响应大小调整阈值)
    • 单独为WebClient实例配置:
    WebClient webClient = WebClient.builder()
            .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(10 * 1024 * 1024)) // 设置为10MB
            .build();
    
  2. 优化后的代码示例:
// 全局复用配置好的ObjectMapper
private final ObjectMapper objectMapper = new ObjectMapper()
        .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

private List<MyPojo> recursiveRestCallMethod(String folderId) throws IOException {
    List<MyPojo> mypojoList = new ArrayList<>();
    
    // 直接将响应反序列化为ObjectNode,不需要中间转String
    ObjectNode node = webClient.get()
            .uri("/my/rest/api/accepting/{folderId}/and/producing/huge/jsonresponse/for/all/files/recursively", folderId)
            .retrieve()
            .bodyToMono(ObjectNode.class)
            .block();
    
    if (node == null) {
        return mypojoList;
    }
    JsonNode entriesNode = node.get("list").get("entries");
    if (entriesNode.isArray()) {
        for (JsonNode jsonNode : entriesNode) {
            JsonNode mainNode = jsonNode.get("entry");
            if (mainNode.get("isFile").asBoolean()) {
                MyPojo pojo = new MyPojo();
                pojo.setNodename(mainNode.get("name").asText());
                // 其余20个字段赋值
                mypojoList.add(pojo);
            }
            if (mainNode.get("isFolder").asBoolean()) {
                String subFolderId = mainNode.get("id").asText().trim();
                mypojoList.addAll(recursiveRestCallMethod(subFolderId));
            }
        }
    }
    return mypojoList;
}
  1. 可选优化:如果响应体积会持续增长,建议改用流式反序列化处理JSON,不需要一次性加载整个JSON到内存,避免出现OOM问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 13:45:04