3

我正在尝试创建springdoc招摇的文档,并且我想以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<String, Object> 将被推断如下 在此处输入图像描述

但我想以更容易理解的方式为引用我的 API 的客户展示 Schema。我可以看到在Github中有一张没有适当解决方案的封闭票。根据我的要求,请求正文应该是类型不可知的动态键值对,因此除了将请求接收为Map<String, Object>. 有没有人用类型实现了更好的方法Map而不是创建自定义请求/响应模型?

4

5 回答 5

4

我有一个 API 端点,请求正文需要一个 HashMap。关于如何解决“示例值”问题的信息不多。 Prasanth 的回答把我带到了正确的地方。我正在发布我的完整解决方案,但所有功劳归他所有。(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
    }
于 2021-03-09T16:31:54.023 回答
3

分享我解决这个问题的工作方法,我已经为@io.swagger.v3.oas.annotations.parameters.RequestBody(content = @Content(schema = @Schema(implementation = Map.class)模式作为字符串问题提供了一个解决方法。

我在 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内部使用的类型。

于 2020-12-02T04:40:18.147 回答
1

这是 springdoc-openapi 库的默认行为,以便忽略 Spring MVC 支持的其他可注入参数。

如果你想改变这种行为,你可以排除它如下:

    SpringDocUtils.getConfig().removeRequestWrapperToIgnore(Map.class);
于 2020-12-01T20:58:08.090 回答
0
  1. 我创建了一个 HashMap 扩展类:

     @Schema(description = "Response-Object Map<String, EcoBalance).")
     public class EcoMap extends HashMap<String, EcoBalance> {
       @JsonIgnore
       @Override
       public boolean isEmpty() {
         return super.isEmpty();
       }
     }
    
  2. 将其用作响应对象

     @ApiResponse(responseCode = "200", content = @Content(mediaType = .., schema = @Schema(implementation = EcoMap.class)), headers = ..
    
  3. 请注意,OpenAPI 3 生成器不会生成这样的客户端模型,但会在 openapi.yml 中正确引用(甚至验证)。

于 2021-06-10T15:14:47.157 回答
0

我想根据我的情况更新rodiri的答案。我不得不将 rodiri 的答案和Ondřej Černobila的答案结合到 SO question 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) 
于 2021-11-10T17:37:18.573 回答