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

Spring REST Docs如何文档化数组类型的请求体参数?

问题分析

你遇到的核心问题是用错了REST Docs的片段类型:requestParameters()是用来文档化URL查询参数的,而你的接口接收的是JSON请求体(通过@RequestBody绑定),而且是数组结构,所以REST Docs自然找不到名为message的请求参数,抛出异常。

正确解决方案:使用requestFields()文档化JSON请求体

要文档化JSON格式的请求体(包括数组结构),你需要使用requestFields()片段,并且通过路径语法指定数组内部的字段。

基础版代码修改

直接针对数组中的message字段进行文档化,修改后的测试代码如下:

MessageContract contractOne = new MessageContract();
contractOne.setMessage("one");
MessageContract contractTwo = new MessageContract();
contractTwo.setMessage("two");
List<MessageContract> list = Arrays.asList(contractOne, contractTwo);

this.webTestClient
    .post().uri("/messages")
    .body(BodyInserters.fromValue(list)) // 建议用fromValue替代fromObject,更符合WebFlux风格
    .exchange()
    .expectStatus().isCreated()
    .expectBody()
    .consumeWith(document("POST messages", 
        requestFields(
            // [].message 表示数组中每个元素的message字段
            fieldWithPath("[].message").description("需要保存的消息内容")
        )
    ));

进阶版:复用字段片段(适合复杂对象)

如果MessageContract有多个字段,或者你想复用字段文档,可以先定义一个字段片段,再通过subsectionWithPath引用:

  1. 先定义可复用的字段片段:
// 可以放在测试类的成员变量中
private final Snippet messageContractFields = fields(
    fieldWithPath("message").description("需要保存的消息内容"),
    // 如果有其他字段,比如id、createTime,都可以在这里添加
    fieldWithPath("id").description("消息ID(可选,由系统生成)").optional()
);
  1. 在测试中引用这个片段:
this.webTestClient
    .post().uri("/messages")
    .body(BodyInserters.fromValue(list))
    .exchange()
    .expectStatus().isCreated()
    .expectBody()
    .consumeWith(document("POST messages", 
        requestFields(
            // [] 表示整个数组,用subsectionWithPath来引用子片段
            subsectionWithPath("[]").description("待保存的消息数组")
                .withSubsectionId("message-contract-fields")
        ),
        // 绑定子片段的内容
        snippetWithPath("message-contract-fields").content(messageContractFields)
    ));
关键知识点说明
  • fieldWithPath("[].xxx"):路径中的[]表示JSON数组的每个元素,xxx是元素对象中的字段名,REST Docs会自动识别这种数组结构。
  • subsectionWithPath:用于引用嵌套的对象/数组结构,配合withSubsectionId可以复用已定义的字段片段,让文档更简洁易维护。
  • 建议使用BodyInserters.fromValue()替代fromObject():fromValue是WebFlux 5.2+推荐的方法,类型更安全。

内容的提问来源于stack exchange,提问作者Aleksey Kozel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:14:53