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

Spring Cloud Gateway出现JSON解析错误(NonClosingInputStream)求因

Spring Cloud Gateway响应JSON解析错误(NonClosingInputStream相关)

可能的原因

  • NonClosingInputStream的设计特性:这个类是Spring用来包装输入流的工具,核心作用是防止流被提前关闭(网关场景下常需要多次读取流)。但部分JSON解析器(如Jackson)在解析时依赖流关闭后的校验逻辑(比如确认是否读到EOF),而NonClosingInputStream不会真正关闭底层流,导致解析器判定数据不完整抛出错误。
  • 响应体未被正确缓存:默认缓存请求体的操作仅针对请求侧,若网关需要对响应体做二次处理(如日志、修改内容),未缓存的响应流被多次读取后,NonClosingInputStream的重复读取可能导致解析器拿到不完整/重复的JSON数据。
  • 过滤器顺序或自定义逻辑问题:自定义过滤器中若错误操作响应流(比如未正确重置流位置、提前读取后未传递完整流),会导致后续解析时流状态异常。

解决方案

  • 显式缓存响应体:在处理响应的过滤器中,确保先缓存响应体再做后续操作。例如使用modifyResponseBody过滤器时,框架会自动缓存响应体:
@Bean
public RouteLocator customRoute(RouteLocatorBuilder builder) {
    return builder.routes()
            .route("backend_route", r -> r.path("/backend/**")
                    .filters(f -> f.modifyResponseBody(String.class, String.class,
                            (exchange, body) -> {
                                // 此处body已被缓存,可安全处理或直接返回
                                return Mono.just(body);
                            }))
                    .uri("http://your-backend-service"))
            .build();
}
  • 调整JSON解析逻辑:避免直接将NonClosingInputStream传入解析器,先读取完整的响应体内容再解析:
// 读取完整响应体为字符串后解析
byte[] bodyBytes = StreamUtils.copyToByteArray(inputStream);
ObjectMapper mapper = new ObjectMapper();
YourResponseDto dto = mapper.readValue(bodyBytes, YourResponseDto.class);
  • 检查过滤器执行顺序:确保缓存响应体的逻辑(如内置的响应缓存过滤器)在所有需要读取响应体的自定义过滤器之前执行。
  • 排查自定义过滤器:检查是否有过滤器未正确处理响应流,比如读取流后未重置位置,或未使用ServerHttpResponseDecorator正确包装响应。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 12:40:00