复杂响应类型的SpringDoc



我正在使用SpringDoc记录一个现有的基于Java的API。我们所有的API都有一个通用的响应对象(如下所示),它有两个字段,一个是状态,另一个是包含实际结果的对象。

class MyResponse {
private String status;
private Object result; 
.........
}

是否有一种方法允许我根据调用的API来记录结果对象的实际运行时类型?例如,如果我的调用是getCustomer()API,我希望为Customer结果对象生成文档;如果我的呼叫是getProduct()API,我希望生成Product结果对象的文档。

您应该使用@ApiResponse来记录将返回的数据类型。以下是您感兴趣的注释-

  • @ApiResponses-表示方法可能返回的响应数组,包括错误响应。公共响应集可以在类级别指定,而特定的一次可以在方法级别提供。

    • value-一个@ApiResponse的数组
  • @ApiResponse-用于描述方法可能返回的特定响应。不能用于类级别。

    • responseCode-表示响应代码的String值,如"200""401"
    • description-响应的描述。通常是HTTP状态消息,如"OK""Unauthorized"
    • content-描述将由该方法返回的内容。有关详细信息,请参阅@Content注释

    重要-401 - Unauthorized等响应可能不会返回任何信息。在这种情况下,内容的首字母应为空@Schema,如下所示。

    @ApiResponse(responseCode = "401", description = "Unauthorized", content = {@Content(schema = @Schema())})
    
  • @Content-描述将由该方法作为响应返回的内容。

    • mediaType-指定API将返回的对象类型如果返回有效响应,则必须指定。可以在类级别定义。例如CCD_ 19或CCD_ 20等
    • schema-将作为方法的响应返回的@Schema对象。有关更多详细信息,请参阅@Schema
  • @Schema-描述将作为响应返回的模式对象(POJO,甚至可以是基元数据类型,相应地设置mediaType)。不指定任何属性意味着对象不会返回任何属性(通常与错误响应一起使用)。

    • implementation-将作为方法的响应返回的类对象的名称。默认为Void.class
  • @Parameter-用于带有其他注释的方法参数,如@RequestParam@PathVariable等。

    • description-描述所需的参数
    • required-Boolean值,指定参数是可选的还是强制的。默认为参数指定的值,如@RequestParam@PathVariable
  • @io.swagger.v3.oas.annotations.parameters.RequestBody-描述处理请求的方法所需的请求正文。

    • description-提供对请求正文的描述
    • required-指定正文是可选的还是强制的Boolean值。默认为true

    记住

    • 虽然也可以使用@Parameter来代替它,但在这种情况下,所有的类obejct都通过引用来解析,因此只保留最后描述的一个
    • 这个@RequestBody与Spring提供的不同,因此必须与@org.springframework.web.bind.annotation.RequestBody一起使用

下面是一个控制器的示例,其中包含文档所需的注释。

@RestController
// the "produces" attribute in @RequestMapping can be used to specify the default mediaType.
@RequestMapping(path = "/api/v1/user/", produces = { MediaType.APPLICATION_JSON_VALUE })
// Defines common tag for all the operartions handled by this class
@Tag(name = "User Operations", description = "APIs for operation on User")
// API responses that might be returned by all the methods in this class
@ApiResponses(value = {
@ApiResponse(responseCode = "400", description = "Bad Request", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = UserErrorResponse.class))}),
@ApiResponse(responseCode = "500", description = "Internal Server Error", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = UserErrorResponse.class))})
})
public class UserController {
// POST Method
// Swagger Annotations
@Operation(summary = "Create User", description = "User-ID is generated and maintained by the service.", tags = {"User Operations"})
@ApiResponses(value = {
@ApiResponse(responseCode = "201", description = "Created", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = UserCreateResponse.class))}),
@ApiResponse(responseCode = "409", description = "User Collision Detected", content = {@Content(schema = @Schema())})
})
// Spring Annotations
@ResponseStatus(code = HttpStatus.CREATED)
@PostMapping(value = "/patients", consumes = { MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<MyResponse> createUser(
// Note the two @RequestBody from Swagger and Spring
@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "A request to create user object") @Valid @RequestBody final User user)
{
...
}

// GET Method
// Swagger Annotations
@ApiResponses(value = {
@ApiResponse(
responseCode = "200", description = "OK", 
// Note the way content is defined for valid objects
content = {@Content(mediaType = "application/json", schema = @Schema(implementation = User.class))})),
@ApiResponse(
responseCode = "404", description = "Not Found",
// Note the way, when no object is returned
content = {@Content(schema = @Schema())})),
})
// Spring Annotations
@ResponseStatus(HttpStatus.OK)
@GetMapping(value = "")
public MyResponse getUser(
@Parameter(required = false, description = "Search by firstName") @RequestParam(required = false) String firstName) 
{
...
}
}

听起来应该使用泛型类型参数而不是Object类型。问题是,Springdoc只知道你告诉它什么,你可以像Debargha建议的那样通知它。然而,这可能会变得非常混乱,而且不太容易维护。幸运的是,它有一个自动检测功能,可以隔离到不同的基本API路径(即".API/v1/产品../.."),这确实考虑了父类,并正确地为它们生成模式。

昨天我遇到了类似的问题,并找到了一个非常紧凑的解决方案,用于为复杂、通用和/或嵌套的java类型声明OpenApi模式。完整描述如下:Open Api Documentation 的通用Java类型和嵌套数组注释

TL:DR;是在@OpenAPIDefinition注释类中注册一个自定义的openApiGroup,然后创建一个标准的SpringBoot@Configuration类。在第二个类中,您放置了空类,用@Schema(desc.optional)进行注释,扩展了MyResponse、MyResponse<列表>等等。任何从自定义组的路径扩展的端点,现在都可以使用这些组合作为返回类型——不是空类的名称,而是实际的东西(例如List)和springdoc会拾取它。

最新更新