如何为Swagger API响应指定通用类型类

25

我大约有40个API,其基本的响应结构如下:

{
    "lastAccessed": "2015-30-08:14:21:45T",
    "createdOn": "2015-30-07:09:04:10T",
    "lastModified": "2015-30-08:14:21:45T",
    "isReadOnly": "false",
    "usersAllowed" : ["Tim", "Matt", "Christine"];
    "noOfEntries": 1,
    "object": [
        "ObjectA": {
             //here object A has its own model
         }
    ]
}

所以,我有一个基本的响应类,使用类型T的泛型,如下所示:
public class Response<T> {
    @ApiModelProperty(value="Last time accessed")
    private String lastAccessed;
    @ApiModelProperty(value="Time when Created ")
    private String createdOn;
    private String lastModified;
    @ApiModelProperty(value="Created on")
    private boolean isReadOnly;
    @ApiModelProperty(value="Users that has access to the object.")
    private List<String> usersAllowed;
    private int noOfEntries;
    private T object;

    //getters and setters
}

对于返回自己字段类型的Object对象的API A,我在控制器中将Response作为API响应返回:

  public class A {
    @ApiModelProperty(value="Name")
    private String name;
    @ApiModelProperty(value="OID")
    private String id;    
    //getters and setters
}    

在控制器中: Response data = new Response(); ResponseEntity response = new ResponseEntity<>(data, HttpStatus.OK);
在Swagger中是否有一种方式可以递归地指定响应对象的模型?例如,我可以使用注释@ApiOperation(response=Response.class),但这不会具有A的模型。

我的回答解决了你的问题吗? - Supun Wijerathne
Marvel77在这里提供的建议(https://github.com/swagger-api/swagger-core/issues/498)对解决这个问题似乎是可行的。 - EmeraldTablet
7个回答

19

我正在使用swagger 2,并且按照以下方式解决了我的问题。

@ApiResponse@ApiOperation中删除'response'属性。然后,swagger将自动为您从方法存根生成200 OK响应类(与响应类是否具有泛型无关)。

@ApiOperation(value = "what your operation does")

@ApiResponses(value = { @ApiResponse(code = 200, message = "Success message") })

更新:你可以通过以下简单的方法来解决这个问题。只需指定Response<MyClass>为返回类型即可。具体做法如下:

  • 在控制器类中,声明一个空的私有类:

    private MyResponseClass extends Response<MyClass>{}

  • 对于swagger规范,请按照以下方式指定:

    @ApiResponse(code = 200, respone=MyResponseClass.class)

请注意,目前swagger不支持泛型。以上两种方法都是解决此问题的临时方法。


2
谢谢。我已经更改为 Swagger 2 并指定了以下内容: public class CreateAccountAvatarRes extends RequestRes <RequestRes.CreateAccountAvatarStatus,String> { - RoutesMaps.com

14

我知道这是一篇旧文章,但对于任何其他寻求答案的人:

可以对 ListSetMap 响应对象执行此操作,但将忽略具有通用类型的任何其他类。 如果您正在使用其中任何一个,则在 responseContainer 字段中指定它们,并在 response 字段中指定推断出的类型。

@ApiResponse(code = 200, responseContainer="List", respone=java.lang.String.class)

8
这个问题最初是在2015年提出的,但是2020年我也在寻找同样的东西。:),因此,我认为添加我在此处发现的内容是相关的。
我正在使用springdoc-openapi-ui(1.5.0),它依赖于Swagger JARs,我理解。由于公共响应类需要一个通用的,实际的API方法必须定义预期的类型。例如:Response<Account>
如果这也适用于您的情况,则定义@ApiResponse -> @Contentschema属性似乎会使Swagger检查通用类型并将其包含在模式中。 Swagger注释@RequestBody -> @Content也适用于相同的事情。

4

我花了一些时间才理解这个问题。现在已经是2022年了(swagger 3)。虽然不是最理想的方法,但是类似下面的代码似乎可以在OpenAPI的API端点中返回泛型。在控制器中:

// use the Response class as the return type
@ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = Response.class)))
public Response<Potato> getPotato(){
     ...
     return Response<Potato>;
}


在这个模型中:
public class Response<T>{
    // use anyOf/allOf for specifying the types of the wrapped in class
    @Schema(anyOf = { Potato.class, Tomato.class })
    T object;

    ...
}

2
根据最近的更新,这里增加了更全面的泛型支持。已测试可与swagger-jaxrs2: 2.2.0swagger-annotations: 2.2.0一起使用。还需要从响应类型中删除任何类定义上的@Schema注释,并且在@ApiResponse注释中没有@Content,只需像这样:
@io.swagger.v3.oas.annotations.Operation(summary = "My summary",
        responses = {@ApiResponse(responseCode = "200", description = "Ok", useReturnTypeSchema = true)}
    )

在我的情况下,响应类型是GenericClass1<GenericClass2<Class3>>


1

我使用了Kotlin,很喜欢它

@ApiOperation(
            value = "Login with email",
            response  = test(Response<AccountResponse>())
    )


fun <T : Any> test(t: T): KClass<out T> = t::class

1
【已解决】我找到了答案,我的解决方案正在运行中 我正在使用OpenApi

        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-ui</artifactId>
            <version>1.6.13</version>
        </dependency>

我花了将近两天的时间,奇迹般地找到了解决方案。

ApiResponse<T> 是我们项目中用于所有响应的泛型响应类。

public class ApiResponse<T extends Object> {
    @Schema(description = "status of the request failed/success", example = "SUCCESS")
    private String status;

    @Schema(description = "code to represent the status of the response", example = "200")
    private Integer statusCode;

    @Schema(description = "message for the response")
    private String message;

    private T data;

    private Integer totalCount;
    private String name;
    private Object extraData;
}

解决方案:只需在通用类型字段上不放置任何@Schema注释,它就可以工作。 对于通用响应的示例,您可以在将用作响应的类的@Schema中添加example

例如:

@Getter
@Setter
@ToString
@Schema(example = "{\n" +
Some JSON example        
}")

public class SomePlanResponseDTO {


最后,在@Controller处。
@Operation(description = "Fetch the plan", responses = {

    })
    @ApiResponses(value = {
            @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", useReturnTypeSchema = false, description = "plan found"),
            @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "404", description = "Subscription plan not found for the current combination of filters", content = {@Content(schema = @Schema(example = "{\n" +
                    "\t\"status\": \"FAILED\",\n" +
                    "\t\"statusCode\": 404,\n" +
                    "\t\"message\": \"not found\"\n" +
                    "}"))}),
            @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "Combination of filters in the request is not appropriate", content = {@Content(schema = @Schema(example = "{\n" +
                    "\t\"status\": \"FAILED\",\n" +
                    "\t\"statusCode\": 400,\n" +
                    "\t\"message\": \"failure\"\n" +
                    "}"))})
    }
    )
    @PostMapping(value = "/somePath", consumes = {MediaType.APPLICATION_JSON_VALUE})
    public ApiResponse<SomePlanResponseDTO > getPlans(@RequestBody SomeRequestDTO someRequestDTO) {
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接