Spring WebClient 解析 JSON 字符串数组的正确方式

雨敏小哥_3781

雨敏小哥_3781

2026-04-27

1016人浏览

原创

Spring WebClient 解析 JSON 字符串数组的正确方式

Spring WebClient 的 toEntityList(String.class) 无法正确解析 JSON 字符串数组(如 ["a","b"]),而是将其整体当作单个字符串返回;这是框架有意设计的行为,需改用 bodyToMono(String[].class) 或适配 NDJSON 格式来解决。

spring webclient 的 `toentitylist(string.class)` 无法正确解析 json 字符串数组(如 `["a","b"]`),而是将其整体当作单个字符串返回;这是框架有意设计的行为,需改用 `bodytomono(string[].class)` 或适配 ndjson 格式来解决。

在使用 Spring WebFlux 的 WebClient 消费 REST 接口时,若后端返回的是纯字符串数组的 JSON(例如 ["D0000019","D0000017"]),直接调用 toEntityList(String.class) 会意外地返回一个仅含单个元素的 List,该元素即为原始 JSON 字符串文本本身(如 "["D0000019","D0000017"]"),而非解析后的字符串列表。这不是 Bug,而是 Spring Framework 的明确设计决策。

根据 Spring 官方文档与核心开发者 Rossen Stoyanchev 的说明,Jackson 编解码器在处理 String.class 与 application/json 媒体类型时存在语义歧义:

  • 它既可能表示「一个被 JSON 序列化的字符串」(如 "hello"),
  • 也可能表示「一个 JSON 数组」(如 ["a","b"])。

为保持一致性并避免流式场景(如 SSE)下的歧义,Spring 默认将 String.class 视为“JSON 字符串字面量”而非“JSON 数组容器”。这意味着 toEntityList(String.class) 实际上不会触发 JSON 反序列化,而只是将响应体原样封装。

✅ 正确解决方案如下:

Wjs Localizing Video
Wjs Localizing Video

用于端到端视频本地化流程的轻量编排器,路由至四个专注子技能——/wjs-transcribing-audio、/wjs-translating-subtitles...

下载

方案一:使用 bodyToMono(String[].class)(推荐)

String[] ids = webClient.get()
    .uri("/myEndpoint")
    .accept(MediaType.APPLICATION_JSON)
    .retrieve()
    .bodyToMono(String[].class)  // 直接反序列化为字符串数组
    .block(); // 阻塞获取(生产环境建议用 Mono.flatMap 等非阻塞链式调用)

List<string> idList = Arrays.asList(ids); // 转为 List(如需)</string>

✅ 优势:简洁、类型安全、完全利用 Jackson 自动反序列化能力。
⚠️ 注意:bodyToFlux(String[].class) 不适用——它会把整个数组当作一个元素发射,而非拆分为多个字符串。

方案二:服务端改用 NDJSON / JSON Lines(适合流式或高并发场景)

若可修改服务端,将响应格式改为换行分隔的 JSON(NDJSON):

"D0000019"
"D0000017"
"D0000016"

客户端配置:

List<string> ids = webClient.get()
    .uri("/myEndpoint")
    .accept(MediaType.APPLICATION_NDJSON) // 显式声明媒体类型
    .retrieve()
    .bodyToFlux(String.class) // 每行自动解析为一个 String
    .collectList()
    .block();</string>

✅ 优势:天然支持流式处理、内存友好;Jackson 默认支持 NDJSON(无需额外配置)。
? 服务端示例(Spring MVC):

@GetMapping(value = "/myEndpoint", produces = MediaType.APPLICATION_NDJSON_VALUE)
public ResponseEntity<flux>> getIds() {
    return ResponseEntity.ok(Flux.fromIterable(Arrays.asList("D0000019", "D0000017")));
}</flux>

❌ 避免踩坑

  • 不要使用 toEntityList(String.class) 或 toEntityList(Object.class) 处理字符串数组;
  • 不要尝试手动 new ObjectMapper().readValue(responseBody, List.class) —— 这绕过了 WebClient 的编解码器链,丢失错误处理与类型推导能力;
  • 若必须保留 List 类型,可在 bodyToMono(String[].class) 后链式转换:
    .map(Arrays::asList)。

总结:Spring 的行为是权衡后的合理设计。面对 JSON 字符串数组,首选 bodyToMono(String[].class),语义清晰、零配置、完全符合 Jackson 反序列化预期;如需扩展性与流式支持,再考虑 NDJSON 协议升级。

相关专题

更多
C语言变量命名
C语言变量命名

c语言变量名规则是:1、变量名以英文字母开头;2、变量名中的字母是区分大小写的;3、变量名不能是关键字;4、变量名中不能包含空格、标点符号和类型说明符。php中文网还提供c语言变量的相关下载、相关课程等内容,供大家免费下载使用。

2023.06.20

3009

3

c语言入门自学零基础
c语言入门自学零基础

C语言是当代人学习及生活中的必备基础知识,应用十分广泛,本专题为大家c语言入门自学零基础的相关文章,以及相关课程,感兴趣的朋友千万不要错过了。

2023.07.25

2268

9

c语言运算符的优先级顺序
c语言运算符的优先级顺序

c语言运算符的优先级顺序是括号运算符 > 一元运算符 > 算术运算符 > 移位运算符 > 关系运算符 > 位运算符 > 逻辑运算符 > 赋值运算符 > 逗号运算符。本专题为大家提供c语言运算符相关的各种文章、以及下载和课程。

2023.08.02

1200

5

c语言数据结构
c语言数据结构

数据结构是指将数据按照一定的方式组织和存储的方法。它是计算机科学中的重要概念,用来描述和解决实际问题中的数据组织和处理问题。数据结构可以分为线性结构和非线性结构。线性结构包括数组、链表、堆栈和队列等,而非线性结构包括树和图等。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.09

1158

4

c语言random函数用法
c语言random函数用法

c语言random函数用法:1、random.random,随机生成(0,1)之间的浮点数;2、random.randint,随机生成在范围之内的整数,两个参数分别表示上限和下限;3、random.randrange,在指定范围内,按指定基数递增的集合中获得一个随机数;4、random.choice,从序列中随机抽选一个数;5、random.shuffle,随机排序。

2023.09.05

1336

5

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

2023.09.20

2098

7

c语言get函数的用法
c语言get函数的用法

get函数是一个用于从输入流中获取字符的函数。可以从键盘、文件或其他输入设备中读取字符,并将其存储在指定的变量中。本文介绍了get函数的用法以及一些相关的注意事项。希望这篇文章能够帮助你更好地理解和使用get函数 。

2023.09.20

3320

8

c数组初始化的方法
c数组初始化的方法

c语言数组初始化的方法有直接赋值法、不完全初始化法、省略数组长度法和二维数组初始化法。详细介绍:1、直接赋值法,这种方法可以直接将数组的值进行初始化;2、不完全初始化法,。这种方法可以在一定程度上节省内存空间;3、省略数组长度法,这种方法可以让编译器自动计算数组的长度;4、二维数组初始化法等等。

2023.09.22

14935

6

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

2023.09.22

549

3

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 20.9万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 4.8万人学习