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

Spring Framework 6中如何以非流式JSON返回Kotlin Flow?

在Spring Framework 6中返回非流式JSON的Kotlin Flow解决方案

问题原因

升级到Spring Boot 3(Spring 6)后,Spring WebFlux的行为发生了关键变化:对于application/json这类非流式媒体类型,不再自动将Flow/Flux收集为List后序列化,而是直接流式传输每个元素。这导致前端收到的是多个独立的JSON对象(无外层数组包裹),触发JSON解析错误:

Unexpected end-of-input: expected close marker for Array

最优解决方案

由于你的服务已经直接返回List<MyClass>,完全不需要额外包装为Flow。最直接且推荐的修复方式是修改控制器的返回类型为List<MyClass>,彻底恢复升级前的非流式JSON数组返回行为:

调整控制器接口

@RequestMapping(
        method = [RequestMethod.GET],
        value = ["/list"],
        produces = ["application/json"]
)
suspend fun list(): ResponseEntity<List<MyClass>>

调整实现代码

override suspend fun list(): ResponseEntity<List<MyClass>> {
    val list: List<MyClass> = service.getMyClass()
    return ResponseEntity.ok(list)
}

无法修改返回类型时的替代方案

如果因契约限制无法更改返回类型,可通过自定义消息转换器强制Spring将Flow<MyClass>序列化为单个JSON数组:

@Configuration
class WebFluxConfig : WebFluxConfigurer {
    override fun configureHttpMessageCodecs(configurer: ServerCodecConfigurer) {
        val objectMapper = ObjectMapper().registerModule(KotlinModule())
        val encoder = Jackson2JsonEncoder(objectMapper, MediaType.APPLICATION_JSON).apply {
            // 移除流式媒体类型配置,强制收集Flow元素为List后序列化
            setStreamingMediaTypes(emptySet())
        }
        configurer.defaultCodecs().jackson2JsonEncoder(encoder)
    }
}

注意:此配置会全局改变Spring WebFlux对application/json下Flow的处理逻辑,需确认对其他接口无负面影响。

总结

优先选择修改返回类型为List<MyClass>的方案,既贴合业务逻辑(服务已返回List),又避免了不必要的流式处理开销,是解决该问题最简洁的方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 07:29:51