使用Java注释,是否可以在其他模式中指定Swagger / OpenAPI模式?

时间:2020-07-16 21:00:39

标签: java spring-boot swagger swagger-ui openapi

我正在尝试使用Swagger UI来创建和部署我的文档以及使用Spring Boot编写的API。我知道Swagger提供了一些注释来帮助在实际的控制器类中编写文档,但是我很难让它们做我需要的事情。

我的问题是我有一个通用的DTO类,每次调用我的API都会返回该类。此DTO具有用于通用对象的contents字段。如果我直接使用对象,我知道我可以使用类似的东西

@ApiResponse(responseCode = "200", description = "Customer found",
    content = @Content(
        schema = @Schema(implementation = Customer.class)))

以便提供对象的JSON表示形式的规范。但是,由于我将所有内容包装在特定的ResponseDTO类中,因此我需要一种方法来指定contents字段的外观,并且我不确定可以使用哪些注释来完成此操作。我觉得肯定应该有类似的东西

@ApiResponse(responseCode = "200", description = "Customer found",
    content = @Content(
        schema = @Schema(implementation = DTO.class, 
                         fields = { "contents" = @Schema(implementation = Customer.class)})))

或类似的东西。我还无法找到有关如何真正完成此操作的说明。我的直觉表明应该有一种方法可以将模式放入模式中,但是也许还有另一种我尚未考虑的解决方案。任何帮助或寻找方向将不胜感激。预先感谢。

3 个答案:

答案 0 :(得分:3)

我知道这篇文章已经过时了,但我还是会发布这个,以防有人遇到类似的问题。

我还必须返回一个对象列表,其中这些对象的字段之一必须根据某些请求参数进行更改。为了在 Swagger 中记录这些子模式(如您所说的模式内的模式),您可以使用 @Schema 注释的 oneOf attribute 并提供您的通用类的列表。< /p>

这是一个例子:

Customer.java

public class Customer {

  // Some other fields...

  @Schema(
      description = "List of generic contents inside Customer",
      oneOf = {Bar.class, Foo.class})
  private List<IContent> contents;

}

IContent.java 只是一些接口(或者它可以是泛型类的任何类):

public interface IContent extends Serializable { }

假设 Foo.javaBar.java 是您的两个泛型类:

public class Bar implements IContent {

  @Schema(description = "Some dummy name field inside Bar")
  private String dummyName;

  @Schema(description = "Some dummy number field inside Bar")
  private Integer dummyNo;

}

public class Foo implements IContent {

  @Schema(description = "Some dummy ID field inside Foo")
  private Long contentID;

}

由此产生的 Swagger UI: swagger-ui

如果您有不同的需求而不是记录通用对象列表,请参阅 allOf and anyOf attributes 以了解其他类型的子模式属性。

答案 1 :(得分:0)

您似乎正在反向进行此操作。我通过使用http://swagger.io

上的编辑器创建一个指定API的.yaml文件来完成此操作

这样,您的.yaml文件可以为每种数据类型指定不同的DTO,并且可以为每种API指定其返回的类型。

此外,您不会发布ResponseDTO类的外观。希望您已将其概括化:

public class ResponseDTO<T> {
  public T getData() { … }
  …
}

但是我不确定甚至拥有自己的对象也不是一个好主意。在我过去的一些项目中,我们为每种数据类型定义了一个单独的响应类,但是它们都做同样的事情!您的框架可能已经为您编写了这样的类。

您正在使用Spring Boot,这就是我所使用的。对于Spring,该类为org.springframework.http.ResponseEntity。 (其他框架可能对此有自己的版本。)并且它已被泛化,因此您可以向其中添加任何数据类型的内容。但是Swagger要求您指定添​​加内容的类型,而不是ResponseEntity类本身。您的ResponseDTO班级正在妨碍您。

因此,如果您想返回一种CustomProduct类型,则您用招摇产生的注释将指定CustomProduct.class,并且您的服务方法将如下所示:

… (more annotations)
@ApiResponses(value = { 
  @ApiResponse(code=200, message="Found", response=CustomProduct.class)
})
public ResonseEntity<CustomProduct> getCustomProduct(…) {
  CustomProduct myCustomProduct = retrieveCustomProduct(…);
  return new ResponseEntity<>(myCustomProduct, HTTPStatus.OK);
}

答案 2 :(得分:0)

我成功使用@Schema标记了类的字段,并且可以正常工作,但是我经常使用它来提供地图信息。

class CreateReq extends DTO {

    @Schema(description="",
        implementation = Products.class)
    Map<String,Map<String,Object>>  products;

}

    // For openapi document only
    private static class Products {
        ProductFields productId1;
        ProductFields productId2;
    }

    // For openapi document only
    private static class ProductFields {
        String field1;
        Object field2;

    }