OpenApi Swagger 2.0:POST请求隐藏只读字段,GET请求保留
解决Swagger 2.0中按HTTP方法控制DTO属性可见性的问题
针对你遇到的POST和GET共用同一DTO但需隐藏部分只读属性的场景,这里有几个更优雅的解决方案,比@ExampleObject的方案更贴合需求:
方案1:Jackson视图(@JsonView)+ Springfox自动适配
这是最常用的方案,利用Jackson的视图机制区分不同场景下的属性展示,同时Springfox(Swagger的Spring实现)能自动识别@JsonView生成对应文档:
- 定义视图标记类:
public class View { public static class Post {} public static class Get {} }
- 在DTO类中标记属性所属视图:
public class FooDTO { // 读写属性,POST请求和GET响应都显示 @JsonView({View.Post.class, View.Get.class}) @ApiModelProperty(value = "普通可读写属性") private String commonProperty; // 只读属性,仅在GET响应中显示 @JsonView(View.Get.class) @ApiModelProperty(value = "只读属性") private String property1; }
- 在控制器方法上指定视图:
@Post @Path("/foobar") @JsonView(View.Post.class) public Object postFoo(@RequestBody FooDTO object) {} @Get @Path("/foobar") @JsonView(View.Get.class) public FooDTO getFoo() {}
这样配置后,Swagger文档里POST的请求体只会展示commonProperty,而GET的响应会显示所有标记了View.Get的属性,完美区分两种场景。
方案2:拆分Request/Response DTO(推荐长期维护)
虽然你想复用类,但拆分DTO其实是更清晰、更易维护的方案,避免后续属性变更时出现混淆:
- 创建基础共用类:
public class BaseFoo { @ApiModelProperty(value = "普通可读写属性") private String commonProperty; // 其他共用属性... }
- 分别定义请求和响应类:
// POST请求用,只包含可写属性 public class FooRequest extends BaseFoo { // 不需要只读属性 } // GET响应用,包含所有属性(包括只读) public class FooResponse extends BaseFoo { @ApiModelProperty(value = "只读属性") private String property1; // 其他只读属性... }
- 控制器方法对应使用不同DTO:
@Post @Path("/foobar") public Object postFoo(@RequestBody FooRequest object) {} @Get @Path("/foobar") public FooResponse getFoo() {}
这个方案的优势在于语义清晰,后续修改属性时不会影响到另一个场景,Swagger文档也会自动生成各自的结构,不需要额外配置。
为什么不推荐@ExampleObject?
@ExampleObject只是用来生成Swagger文档中的示例数据,无法真正控制属性的可见性——用户仍然能在POST请求体的模型中看到只读属性,只是示例里没显示,这不符合你“隐藏只读属性”的核心需求。
内容的提问来源于stack exchange,提问作者KMcW
相关产品推荐
相关产品推荐

