How to specify a generic type class for Swagger API response

as3rdaccount picture as3rdaccount · Nov 1, 2015 · Viewed 16.7k times · Source

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.

Answer

Supun Wijerathne picture Supun Wijerathne · Feb 6, 2018

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.