Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Document a @RequestBody Map in Swagger

I'm creating the swagger file for the documentation of the various APi. In a controller I have the case where I request a RequestParam and a RequestBody:

@PostMapping("/message-now/save-with-params")
    @Timed(value = MetricsTimerConstants.storeMessageWithParamsTimer)
    public ResponseEntity<Object> saveMessageWithParams(@RequestBody Map<String, Object> request,
            @RequestParam List<String> params) { .....

Is there a way to define Lists and Maps in OpenApi? searching I found nothing on this subject

like image 546
Numero 21 Avatar asked Dec 04 '20 11:12

Numero 21


People also ask

How do I create a Swagger document for existing REST API?

Head over to Swagger Inspector, and insert the end point of the resource you want to have documented. You can then navigate to the right panel from the History section of Swagger Inspector, and click "Create API definition" to create the OAS definition.


1 Answers

TL;DR : HashMaps and Lists are indeed supported in the OpenAPI spec .

Well , to answer your question in detail let me first make you understand how lists and maps work in OpenAPI , though they may not look straight forward and documented that clearly in the documentation by naming , but they do exist .

1. Lists

Lists are nothing but basically arrays . So OpenAPI does provide parameter input of type query to support that . While stating the type of parameter , you also need to specify data-type of the parameter as shown below to make it work .

enter image description here

As , shown above , you need to define items section where you define type of the elements in the list , in your case , it is a list of strings . So , if you generate a client code for this definition , you will see that it generates a list of strings in the api definition as below .

enter image description here

As you can see , it gets generated as a @RequestParam type of input value . So , you may understand now that lists do exists in the OpenAPI definition in this manner .

2. Maps

For maps as well , they are documented popularly as dictionary in the OpenAPI documentation which is same thing as a Java HashMap . In OpenAPI, we can make use of the additionalProperties attribute while defining a model in the spec . For example , you want a request body as a HashMap in your Rest API , i.e

@RequestBody Map<String, Object> request

To make this work , you will write your OpenAPI specification something like as below :

enter image description here

Note: Above Request model that we created , should be used in the ref section of API endpoint as a "body" input type parameter as shown below .

enter image description here

Verification :

Now , let's verify that the OpenAPI definition model that we created above, will get translated into a HashMap , when the code is generated . So , lets generate a Spring based Server Code by going to https://editor.swagger.io/ , then after creating your API definition go to Generate Server > spring . It will generate a Spring based API code based on the API definition that you would have created for your use-case . So , if you go to that zip file and look inside src/main/java/io/swagger/api , there will a file named as <YOUR_API_NAME>Api.java (In my case , just to test your scenario, i edited the default Pet API provided by swagger automatically on https://editor.swagger.io/ , so in my case file name was PetApi.java ) . So , when i looked at the generated code for the API endpoint that requires a "request" map to receive the request , it was like below .

enter image description here

Now , you may think why its just @RequestBody Request request and not @RequestBody HashMap<String,Object> request right ? But let me tell you , its a HashMap only and not an object !! But how ?? . To answer that question , i went to following location in the generated source code folder at path src/main/java/io/swagger/model and looked for a file called Request.java (In your case your file name may differ based upon what you name your map in your OpenAPI spec , in my case i had named it as Request) . Basically swagger keeps all generated models defined in OpenAPI spec at this location . So , looking at the Request.java model class , i found this at the class level declaration .

enter image description here

So, by now you would have understood that the generated model class is extending the Map of type HashMap<String,Object> , so basically Request is a HashMap as it extends the HashMap<String,Object>, exactly what you desired for . Just to make things , more clear just see below image , where i tried to invoke a map based method on the Request object and it's working , as my IDE is giving suggestions for HashMap related methods indicating that it is indeed a HashMap !!

enter image description here

Conclusion:

So , We can easily deduce that HashMaps (aka dictionaries) and Lists (aka arrays) are available in the OpenAPI spec for designing data-models so that when you generate them you can convert them to corresponding data structures as shown above by digging in the documentation deeper . You can read more about them by going at following links :

https://swagger.io/docs/specification/data-models/dictionaries/ https://swagger.io/docs/specification/describing-parameters/

Hope that helps !! :)

like image 91
Saurabh Chaturvedi Avatar answered Sep 21 '22 05:09

Saurabh Chaturvedi