Warm tip: This article is reproduced from serverfault.com, please click

Document a @RequestBody Map in Swagger

发布于 2020-12-04 11:28:34

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

Questioner
Numero 21
Viewed
0
Saurabh Chaturvedi 2020-12-09 22:20:19

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 !! :)