Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Documenting a wrapped REST response using swagger UI

I have a WidgetDto that I have annotated with swagger UI annotations. The final response wraps a list of WidgetDtos with a layer of metadata (per page 21 of this RESTful best practices document). For example:

{
  "data" : [ 
    {
      "id" : 1234,
      "prop1" : "val1"
      ...
    },
    {
      "id" : 5678,
      "prop1" : "val2"
      ...
    }, 
    ...
  ]
}

My java code looks like this:

@GET
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(
        value = "Get all widgets.",
        response = WidgetDto.class
)
@ApiResponses(value = {
        @ApiResponse(code = 200, message = "Returns the list of widgets.")
})
public Response getWidgets() {
  List<WidgetDto> widgets;
  ...
  Map<String, Object> responseBody = new HashMap<>();
  responseBody.put("data", widgets);
  return Response.ok(responseBody).build();
}

I'd like to reuse this pattern on multiple resources, and I don't want to create list DTOs for every response type. Is there an elegant way to use swagger to document these types of response bodies?

like image 353
Bill Avatar asked Jul 07 '15 21:07

Bill


1 Answers

Your metadata is not a part of your resource but it's a part of your resource's representation.

In my case, responses types are 'application/hal+json' and 'application/json', each of them use a different wrapper with different metadatas. To solve this problem, I created an extern document to explain these two wrappers and for each of them, how a single resource and a list of resources are represented with metadata.

I think my choice is correct because I separate the resource of its representations (per page 7 'Manipulation of Resources Through Representations' of this RESTful best practices document)

In your case, you returns a list of WidgetDtos, the layer of metadata is a part of the representation of your resource.

However, you can use a generic class like Resource and Resources used by spring-hateoas :

public class Resources<T> implements Iterable<T>  {
    private final Collection<T> content;
    Resources(Iterable<T> content) {
        this.content = new ArrayList<T>();
        for (T element : content) {
            this.content.add(element);
        }
    }
}

And use it like this:

@GET
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(
        value = "Get all widgets.",
        response = WidgetDto.class
)
@ApiResponses(value = {
        @ApiResponse(code = 200, message = "Returns the list of widgets.")
})
public Response getWidgets() {
  List<WidgetDto> widgets;
  ...
  return Response.ok(new Resources<WidgetDto>(widgets)).build();
}
like image 85
Nelson G. Avatar answered Nov 08 '22 15:11

Nelson G.