使用Spring WebClient反序列化整数列表遇到的问题
WebClient处理整数JSON数组时bodyToFlux返回空的问题
哈哈,这个问题我之前用WebClient的时候也踩过坑!咱们来一步步拆解原因和解决方案:
为什么bodyToFlux会返回空Flux?
核心原因是WebClient的bodyToFlux对JSON数组的默认解析逻辑和你预期的不一样:
bodyToFlux<T>默认期望的是流式的JSON元素——比如响应是换行分隔的单个JSON值(像1\n2\n3\n4这种),或者分块传输中每个块对应一个JSON元素。- 但你的响应是一个完整的JSON数组
[1,2,3,4],Jackson会把整个数组当成一个单独的对象处理,而不是自动拆分成单个的Int元素,自然匹配不上Flux<Int>,所以返回空。
而bodyToMono<List<Int>>能正常工作,是因为它明确告诉Jackson:“把整个响应体解析成一个List
有没有更优雅的方式替代冗余的flatMapIterable?
当然有,给你两种常用方案:
方案1:用ParameterizedTypeReference配合flatMapMany(Kotlin友好写法)
这种写法比直接用flatMapIterable更清晰,本质都是把解析出来的List转成Flux:
client.get() .uri("/achievements") .retrieve() .bodyToMono(object : ParameterizedTypeReference<List<Int>>() {}) .flatMapMany { Flux.fromIterable(it) } .doOnNext { println(it) } .doOnError { it.printStackTrace() } .blockLast()
方案2:配置Jackson让它支持流式解析数组
通过修改WebClient的Jackson解码器配置,开启USE_JAVA_ARRAY_FOR_JSON_ARRAY特性,这样Jackson会把JSON数组当成Java数组处理,bodyToFlux<Int>就能自动拆分元素了:
// 先配置支持Kotlin的ObjectMapper val objectMapper = ObjectMapper().registerModule(KotlinModule()) .enable(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY) // 构建配置好的WebClient val webClient = WebClient.builder() .codecs { configurer -> configurer.defaultCodecs().jackson2JsonDecoder(Jackson2JsonDecoder(objectMapper)) } .build() // 现在直接用bodyToFlux<Int>就正常了 webClient.get() .uri("/achievements") .retrieve() .bodyToFlux<Int>() .doOnNext { println(it) } .doOnError { it.printStackTrace() } .blockLast()
补充:bodyToFlux和bodyToMono并不是只适用于POJO
它们完全支持原生类型、包装类、集合等类型,只是处理JSON数组的逻辑有差异:
bodyToFlux<T>:适合处理多个独立JSON元素的流,或者配置Jackson后处理JSON数组。bodyToMono<List<T>>:适合直接处理单个JSON数组,解析成List对象后再转Flux也很方便。
内容的提问来源于stack exchange,提问作者Dolvic
相关产品推荐
相关产品推荐

