Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to specify a generic type class for Swagger API response

Tags:

I have about 40 APIs that have similar base response structure as follows:

{     "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          }     ] } 

So I have a base response class taking a generic of type T as follows:

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 } 

So for the API A, which returns the Object of type with its own fields, I am returning Response as the API response in the controller:

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

In the controller: Response data = new Response(); ResponseEntity response = new ResponseEntity<>(data, HttpStatus.OK);

Is there a way in swagger I can specify the model of the response object recursively? For example, I could have the annotation @ApiOperation(response=Response.class) but that would not have the model for A.

like image 352
as3rdaccount Avatar asked Nov 01 '15 05:11

as3rdaccount


People also ask

How do you declare a generic class?

To update the Box class to use generics, you create a generic type declaration by changing the code "public class Box" to "public class Box<T>". This introduces the type variable, T, that can be used anywhere inside the class. As you can see, all occurrences of Object are replaced by T.

What is a generic type parameter?

Generic Methods A type parameter, also known as a type variable, is an identifier that specifies a generic type name. The type parameters can be used to declare the return type and act as placeholders for the types of the arguments passed to the generic method, which are known as actual type arguments.

What are generic classes?

Generic classes encapsulate operations that are not specific to a particular data type. The most common use for generic classes is with collections like linked lists, hash tables, stacks, queues, trees, and so on.

What is @schema annotation in swagger?

The annotation may be used to define a Schema for a set of elements of the OpenAPI spec, and/or to define additional properties for the schema. It is applicable e.g. to parameters, schema classes (aka "models"), properties of such models, request and response content, header.


1 Answers

I am using swagger 2 and following resolved this problem for me.

Remove 'response' property from both @ApiResponse and @ApiOperation. Then swagger will automatically generate the response class for you for 200 OK from method stubs (irrespective of whether with/without generics in response class).

@ApiOperation(value = "what your operation does")  @ApiResponses(value = { @ApiResponse(code = 200, message = "Success message") }) 

Update: You can do this simple work around. Just say you want to output Response<MyClass> as response return type. You can do,

  • In controller class, specify an empty private class like this

    private MyResponseClass extends Response<MyClass>{}

  • And for the swagger spec, specify like this,

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

Remember that at the moment, swagger doesn't support generics. Above two are just workarounds.

like image 142
Supun Wijerathne Avatar answered Sep 24 '22 02:09

Supun Wijerathne