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引用:
- 先定义可复用的字段片段:
// 可以放在测试类的成员变量中 private final Snippet messageContractFields = fields( fieldWithPath("message").description("需要保存的消息内容"), // 如果有其他字段,比如id、createTime,都可以在这里添加 fieldWithPath("id").description("消息ID(可选,由系统生成)").optional() );
- 在测试中引用这个片段:
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
相关产品推荐
相关产品推荐

