Swagger-core: Unable to represent empty response body (HTTP 204)

Created on 21 Sep 2017  路  11Comments  路  Source: swagger-api/swagger-core

Description

In many of the APIs that I'm developing, we have cases where we reporting success does not require a response body (ex: deleting an entity, there is nothing to say if it works since the entity is gone.)

Unfortunately, it appears that swagger annotations cannot (currently) handle this.

Example:

Both this:

    @ApiResponses({
        @ApiResponse(code = 204, message = "identity deleted sucessfully",
                    response = void.class),
        @ApiResponse(code = 404, message = "no such user or identity")
    })

and this:

    @ApiResponses({
        @ApiResponse(code = 204, message = "identity deleted sucessfully"),
        @ApiResponse(code = 404, message = "no such user or identity")
    })

produce the following spec (irrelevant portions omitted):

        "responses" : {
          "204" : {
            "description" : "identity deleted sucessfully",
            "schema" : {
              "type" : "object"
            }
          },
          "404" : {
            "description" : "no such user or identity"
          }
        }

It seems clear to me that this behavior is unarguably wrong, as void has a very well-understood meaning of, well... nothing. As it stands, ReDoc, swagger-ui, et al. will display the 204 response as though it will produce JSON consisting of {} (an empty object). This is incorrect.

Suggested resolution

When @ApiResponse#response is Void.class or void.class, omit the schema property in the resulting spec.

Additionally, consider adding special case handling to 204, since its meaning according to the HTTP spec strongly implies that there should be no response. (IIRC 404 already works like this unless you specify a response property for it.)

Workaround

None. Document incorrect behavior and warn your API documentation's users.

Top Issue!

Most helpful comment

Found the workaround,
As the default behavior of @ApiOperation is to return the return type of method, so for every status, the return type of method will be returned.
If you want to send empty response then write
@ApiResponse(code = 204, message = "No User found for that Id",response = Object.class)

And in the SwaggerConfig write

 @Bean
    public Docket productApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .useDefaultResponseMessages(false)
                .directModelSubstitute(Object.class, java.lang.Void.class);          
    }

So whenever an Object.class is returned swagger will automatically convert it into Void.class

All 11 comments

Hi @rtomsick,

I can see that removing the 'response = void.class' is the workaround.

Thanks,
Mohammed Rizwan

At least as it behaves on my system no, that is not a workaround. The resulting schema remains whether I specify

@ApiResponse(code = 204, message = "identity deleted sucessfully",
                    response = void.class)

or

@ApiResponse(code = 204, message = "identity deleted sucessfully")

I agree with you that the correct behavior for a 204 would be to assume no response unless otherwise specified, but that is not what currently happens.

Hi @rtomsick,

From the example and the spec produced posted by you, I can see that
@ApiResponse(code = 404, message = "no such user or identity") produces the below spec without the schema field

"404" : {
            "description" : "no such user or identity"
  } 

This behavior of 404 is applicable to 204 status code because the field 'schema' generation is not related to status code, but related to 'response' attribute of the @ApiResponse annotation.

Thanks,
Mohammed Rizwan

Yes, that is the correct (default) behavior for 404. If no @ApiResponse#response property is specified, no schema property will exist in the resulting spec.

But if you re-read my previous message, you'll see that the incorrect schema appears for 204 regardless of whether or not I provide an @ApiResponse#response property.

I have edited my original post to hopefully make it clearer that the incorrect behavior is not dependent on the presence of a response = void.class property.

Can you specify the version of swagger-annotation jar to reproduce this issue?

Reproduced most recently w/ 1.5.16

I may be a bit late to the party, but the following workaround does the trick for me, in case anyone with the same issue is stumbling across this issue:
@ApiResponse(code = 204, message = "identity deleted sucessfully", response = Object.class)

For me the problem was, that the @ApiResponse inherited the response type from @ApiOperation. So I had to override it with something empty. "Void.class" would seem like the right choice, but this is the default value, thus leading to the inheritance from @ApiOperation.

Found the workaround,
As the default behavior of @ApiOperation is to return the return type of method, so for every status, the return type of method will be returned.
If you want to send empty response then write
@ApiResponse(code = 204, message = "No User found for that Id",response = Object.class)

And in the SwaggerConfig write

 @Bean
    public Docket productApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .useDefaultResponseMessages(false)
                .directModelSubstitute(Object.class, java.lang.Void.class);          
    }

So whenever an Object.class is returned swagger will automatically convert it into Void.class

@vipingupta5352 Good workaround, but then you end up with a schema referring to Void instead of it being omitted:

        "responses" : {
          "200" : {
            "description" : "Completed successfully",
            "schema" : {
              "$ref" : "#/definitions/Void"
            }
          }
        }

I've found that specifying void.class for the response type of @ApiOperation will result in the schema block being removed:

    @ApiOperation(value = "Response body should be empty", response = void.class)

results in:

        "responses" : {
          "200" : {
            "description" : "Completed successfully"
          }
        }

This doesn't seem to be reproducible in latest version, providing annotations as in example below results in a response without schema :

@ApiResponses({
        @ApiResponse(code = 204, message = "identity deleted sucessfully"),
        @ApiResponse(code = 404, message = "no such user or identity")
    })

Closing ticket, please reopen if you're still experiencing issues (please provide the version, environment and full annotated code)

I have had the same issue with Swagger and springfox-boot-starter version 3.0.0

I could eliminate the displaying of a repsonse body, by annotating the controller method with the following:
@ResponseStatus(HttpStatus.NO_CONTENT) @ResponseBody

Was this page helpful?
0 / 5 - 0 ratings