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
相关产品推荐
相关产品推荐

