Spring WebFlux返回Flux<String>未生成JSON数组而是拼接字符串的问题
嘿,作为Spring WebFlux新手碰到这个问题太正常了!我来给你理清楚为什么会这样,以及怎么直接返回字符串数组:
首先先把你的代码整理一下,方便看清楚问题:
class Wrapper(val data: String) @RestController class Test() { @RequestMapping("/wrapped") // 返回有效JSON数组: [{"data":"Hello"},{"data":"World"}] fun b() = Flux.just(Wrapper("Hello"), Wrapper("World")) @RequestMapping("/raw") // 返回无效结果:HelloWorld fun a() = Flux.just("Hello", "World") }
问题到底出在哪?
当你返回Flux<String>时,Spring WebFlux的默认行为是把它当作文本流来处理——每个字符串元素会被直接输出到响应体里,没有任何JSON序列化的包裹逻辑,所以最终就变成了HelloWorld这种拼接后的纯文本。
而返回Flux<Wrapper>时,因为Wrapper是自定义对象,Spring会自动启用JSON编码器,把每个对象序列化为JSON对象,再组合成数组输出,所以得到的是正确的JSON格式。
至于你说Array<String>能正常工作,是因为Array本身是一个完整的集合对象,Spring会把它当作单个JSON数组来序列化,而不是像Flux<String>那样流式输出每个元素。
直接返回字符串数组的解决方案
这里给你几种实用的方式,按需选择:
方式1:把Flux转为Mono<List>并指定媒体类型
这是最简洁的方案——把流式的Flux收集成一个List,返回Mono<List<String>>,同时明确告诉Spring要返回JSON格式:
import org.springframework.http.MediaType @RestController class Test() { @RequestMapping("/wrapped") fun b() = Flux.just(Wrapper("Hello"), Wrapper("World")) @RequestMapping("/raw", produces = [MediaType.APPLICATION_JSON_VALUE]) fun a(): Mono<List<String>> = Flux.just("Hello", "World").collectList() }
方式2:用ServerResponse手动构建响应
如果需要更灵活的响应控制(比如自定义状态码、响应头),可以用ServerResponse来明确构建JSON数组响应:
import org.springframework.web.reactive.function.server.ServerResponse import org.springframework.http.MediaType @RestController class Test() { @RequestMapping("/wrapped") fun b() = Flux.just(Wrapper("Hello"), Wrapper("World")) @GetMapping("/raw") fun a(): ServerResponse { val stringFlux = Flux.just("Hello", "World") return ServerResponse.ok() .contentType(MediaType.APPLICATION_JSON) .body(stringFlux.collectList(), List::class.java) } }
方式3:全局配置编码器(谨慎使用)
如果你希望所有返回Flux<String>的端点都默认返回JSON数组,可以全局修改WebFlux的编码器配置,但这种方式会影响所有端点,所以只在全局需要这个行为时使用:
import org.springframework.context.annotation.Configuration import org.springframework.http.codec.ServerCodecConfigurer import org.springframework.web.reactive.config.WebFluxConfigurer @Configuration class WebFluxGlobalConfig : WebFluxConfigurer { override fun configureHttpMessageCodecs(configurer: ServerCodecConfigurer) { val jsonEncoder = configurer.defaultCodecs().jackson2JsonEncoder() // 让JSON编码器处理String类型的流 configurer.defaultCodecs().jackson2JsonEncoder(jsonEncoder) } }
验证效果
修改后访问/raw端点,你就能得到预期的JSON数组响应了:
["Hello","World"]
内容的提问来源于stack exchange,提问作者Artem Yarulin
相关产品推荐
相关产品推荐

