Swagger 声明 schema = @Schema(implementation = Map.class) 将 Schema 表示为 swagger-ui 中的 String
Posted
技术标签:
【中文标题】Swagger 声明 schema = @Schema(implementation = Map.class) 将 Schema 表示为 swagger-ui 中的 String【英文标题】:Swagger declaration schema = @Schema(implementation = Map.class) represents Schema as String in swagger-ui 【发布时间】:2021-03-08 15:19:55 【问题描述】:我正在尝试创建springdoc
swagger 文档,并且我想以更易读的方式为客户表示具有数据类型Map<String, Object>
的请求正文。但是当我声明@io.swagger.v3.oas.annotations.parameters.RequestBody(content = @Content(schema = @Schema(implementation = Map.class)
时,Schema 会以String
的形式出现(附上下面的屏幕截图)
方法声明
@Operation(security = @SecurityRequirement(name = "bearer-key"), summary = "Create Data", operationId = "createData", description = "Create createData for the **`type`**. ")
@ApiResponses(value =
@ApiResponse(responseCode = "201", description = "Data created", content = @Content(schema = @Schema(implementation = Map.class),
examples = @ExampleObject(value = "\n" +
" \"id\": \"927d810c-3ac5-4584-ba58-7c11befabf54\",\n" +
""))),
@ApiResponse(responseCode = "400", description = "BAD Request"))
@PostMapping(value = "/data/type", produces = APPLICATION_JSON_VALUE, consumes = APPLICATION_JSON_VALUE)
@io.swagger.v3.oas.annotations.parameters.RequestBody(content = @Content(schema = @Schema(implementation = Map.class),
examples = @ExampleObject(value = "\n" +
" \"label\":\"tourism\",\n" +
" \"location\":\"France\"\n" +
" ")))
ResponseEntity<Map<String, Object>> createData(@Parameter(name = "type", required = true) @PathVariable("type") String type, @Parameter(name = "request payload") @Valid @RequestBody Map<String, Object> body);
虽然Spring boot会根据方法签名自动推断出类型,但是对于Map
这个数据类型还不清楚。例如,默认情况下,类型 Map
但我想以一种更易于理解的方式向引用我的 API 的客户展示 Schema。我可以看到Github 中有一张没有适当解决方案的封闭票。根据我的要求,请求正文应该是类型不可知的动态键值对,因此除了以Map<String, Object>
接收请求之外别无他法。有没有人使用Map
类型实现了更好的方法,而不是创建自定义请求/响应模型?
【问题讨论】:
看到问题here? 是的,Spring MVC 支持的所有可注入参数类型都被大摇大摆地排除和忽略,完整列表可在link 中找到,建议的解决方案不是最优雅的,可能不适合所有要求主要是如果您的回复类型是Map<String, Object>
,那么建议的方法将不适合
【参考方案1】:
我有一个 API 端点,请求正文需要一个 HashMap。关于如何解决“示例值”问题的信息不多。 Prasanth's answer 带我到正确的地方。我正在发布我的完整解决方案,但所有功劳归于他。 (PS:我试图赞成他的回答,但我没有足够的“积分”)
配置方面:
@Configuration
@OpenAPIDefinition
public class DocsConfiguration
@Bean
public OpenAPI customOpenAPI()
Schema newUserSchema = new Schema<Map<String, Object>>()
.addProperties("name",new StringSchema().example("John123"))
.addProperties("password",new StringSchema().example("P4SSW0RD"))
.addProperties("image",new StringSchema().example("https://robohash.org/John123.png"));
return new OpenAPI()
//.servers(servers)
.info(new Info()
.title("Your app title")
.description("App description")
.version("1.0")
.license(new License().name("GNU/GPL").url("https://www.gnu.org/licenses/gpl-3.0.html"))
)
.components(new Components()
.addSchemas("NewUserBody" , newUserSchema)
);
控制器端:
@io.swagger.v3.oas.annotations.parameters.RequestBody(
content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = @Schema(ref = "#/components/schemas/NewUserBody")))
@PostMapping("/v1/users")
public Response<User> upsertUser(@RequestBody HashMap<String,Object> user)
//Your code here
【讨论】:
【参考方案2】:分享我解决此问题的工作方法,我已针对 @io.swagger.v3.oas.annotations.parameters.RequestBody(content = @Content(schema = @Schema(implementation = Map.class)
解决方案,Schema iscoming as String 问题。
我在 OpenAPI bean 声明中声明了一个名为 Map 的自定义模式,如下所示
new OpenAPI()
.components(new Components()
.addSchemas("Map", new Schema<Map<String, Object>>().addProperties("< * >", new ObjectSchema())
))
.....
.....
并在下面的 Schema 声明中使用上述模式
@io.swagger.v3.oas.annotations.parameters.RequestBody(
content = @Content(mediaType = APPLICATION_JSON_VALUE,
schema = @Schema(ref = "#/components/schemas/Map"))
上面的方法可以用来代替ApiResponse
也如下
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200",
content = @Content(mediaType = APPLICATION_JSON_VALUE,
schema = @Schema(ref = "#/components/schemas/Map"))
注意:如果我们使用上述自定义架构方法,我们不需要更改或忽略SpringDoc
在内部使用的任何类型。
【讨论】:
谢谢!要通过 openapi-generator-maven-plugin 生成 ApiClient,我必须设置 skipValidateSpec=true 因为安装时的模式映射【参考方案3】:这是 springdoc-openapi 库的默认行为,以便忽略 Spring MVC 支持的其他可注入参数。
https://docs.spring.io/spring/docs/5.1.x/spring-framework-reference/web.html#mvc-ann-arguments如果你想改变这种行为,你可以排除它如下:
SpringDocUtils.getConfig().removeRequestWrapperToIgnore(Map.class);
【讨论】:
【参考方案4】:我创建了一个 HashMap 扩展类:
@Schema(description = "Response-Object Map<String, EcoBalance).")
public class EcoMap extends HashMap<String, EcoBalance>
@JsonIgnore
@Override
public boolean isEmpty()
return super.isEmpty();
将其用作响应对象
@ApiResponse(responseCode = "200", content = @Content(mediaType = .., schema = @Schema(implementation = EcoMap.class)), headers = ..
请注意,OpenAPI 3 生成器不会生成这样的客户端模型,但会在 openapi.yml 中正确引用(甚至进行验证)。
【讨论】:
【参考方案5】:我想根据我的情况更新rodiri's answer。我不得不将 rodiri 的答案和这个 answer by Ondřej Černobila 与 SO 问题 SpringDoc - How to Add schemas programmatically 结合起来。我正在使用 java 11、spring-boot-starter-parent 2.5.6 和 springdoc-openapi-ui 1.5.12,我相信它们正在使用 swagger 3.52.5
<!-- https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-ui -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.5.12</version>
</dependency>
我的配置
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.models.media.ObjectSchema;
import io.swagger.v3.oas.models.media.StringSchema;
import org.springdoc.core.customizers.OpenApiCustomiser;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@OpenAPIDefinition
public class DocsConfiguration
@Bean
public OpenApiCustomiser openApiCustomiser()
return openApi ->
var NewUserBodySchema = new ObjectSchema()
.name("NewUserBody")
.title("NewUserBody")
.description("Object description")
.addProperties("name", new StringSchema().example("John123"))
.addProperties("password", new StringSchema().example("P4SSW0RD"))
.addProperties("image", new StringSchema().example("https://robohash.org/John123.png"));
var schemas = openApi.getComponents().getSchemas();
schemas.put(NewUserBodySchema.getName(), NewUserBodySchema);
;
对于我的端点,我使用的是返回 Map 的 get,因此它与接受的答案不同。
@GetMapping(value = "/userId")
@Operation(
summary = "Get Something",
description = "Some desciption",
responses =
@ApiResponse(
responseCode = "200",
description = "The Map Response",
content =
@Content(
mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = @Schema(ref = "#/components/schemas/NewUserBody")
)
)
)
public ResponseEntity<Map<String, Object>> getMap(@PathVariable String userId)
【讨论】:
以上是关于Swagger 声明 schema = @Schema(implementation = Map.class) 将 Schema 表示为 swagger-ui 中的 String的主要内容,如果未能解决你的问题,请参考以下文章
FastAPI学习-9. Swagger文档输出请求示例example
compojure-api/schema/swagger 中的非必需参数?
要求数组在 Swagger Schema Object 定义中至少包含一个元素
RestAssured 中的无效 JSON Schema 异常,同时针对来自 swagger 的模式进行验证