# How to write REST document with Swagger ### I. Why Swagger - It's popularity. Swagger is the most widely adopted documentation and specification standard for REST Services. - Designed for REST so it's easy to use with very clear sample templates. - Beautiful UI. The plain text you write can be converted to nice html with SwaggerUI. - Auto-generate Code. You can auto-generate client and server code (interface part) based on the Swagger spec, which makes sure that they are consistent. ### II. How to create REST document with Swagger You can use [SwaggerEditor](https://editor.swagger.io/#/) as a starter. And if you have just a few api, you can totally write the specification in 1 file. However, having a structure would be a better idea because clean code is better code, and it's also helpful when you want to add or edit your api later. We'll be using the sample api doc from [SwaggerEditor](https://editor.swagger.io/#/) and re-arrange some pet's apis into our structure. #### 1. Create your openapi folder ![openapi folder](https://i.imgur.com/XLFNGga.png) As you can see from the structure, we will not put all api specs in single `index.yaml` file. Instead, we separate them and define references to those files in `index.yaml` #### 2. `openapi/index.yaml` ```yaml! openapi: "3.0.0" info: title: Swagger Petstore - OpenAPI 3.0 description: This is a sample Pet Store Server based on the OpenAPI 3.0 specification version: "1.0.0" servers: - url: https://petstore3.swagger.io variables: basepath: default: /api/v3 paths: /pet: $ref: ./paths/pet/index.yaml /pet/{petId}: $ref: ./paths/pet/pet_id/index.yaml components: schemas: $ref: ./schemas/index.yaml parameters: $ref: ./parameters/index.yaml ``` - openapi: This is to say what version we're using. - info: basic info, includes: + title: The title of your API documentation. + description: A description of your API. + version: The version of your API - servers: server definition, includes: + url: The server where your REST API is located. + basePath: The path on the server where your REST API is located. This can be defined in url instead of defining in basepath. - paths: are the api endpoints - component: includes schemas (for request and response), and parameters And now, instead of one long specication file, we put it into smaller chunks which is easier to modify later. #### 3. `openapi/paths` Now in path folder, create directories as we have define in $ref. Let's take pet directory as an example, it'll look something like this. ![path folder](https://i.imgur.com/HAvnLCn.png) In the path file, you define the HTTP methods (e.g. GET, POST, PUT) that the path can be used with. Then, continue to separate parameters, request body, and response in schemas folder. ```yaml! # example on /pet path post: tags: - pet summary: Add a new pet to the store description: Add a new pet to the store operationId: addPet requestBody: description: Create a new pet in the store content: application/json: schema: $ref: '../../schemas/request/petDetails.yaml' required: true responses: '200': description: Successful operation content: application/json: schema: $ref: '../../schemas/response/petDetails.yaml' '405': description: Invalid input # example on /pet/{petId} path get: tags: - pet summary: Find pet by ID description: Returns a single pet operationId: getPetById parameters: - $ref: '../../../parameters/petId.yaml' responses: '200': description: successful operation content: application/json: schema: $ref: '../../../schemas/response/petDetails.yaml' '400': description: Invalid ID supplied '404': description: Pet not found ``` - tags: is to separate your document into section. Here you have pet section, store section and user section. It's to make the document clear, not a compulsory. - summary: A short description of the service. There is also a description property for a more lengthy description, if necessary. - description: is a longer details of this api - operationId: the http method id - parameters: The different parameters that the service accepts. It is both parameters in the HTTP header, URI path, query string and HTTP request body. - responses: The possible responses that the service can return. (HTTP Status Code): You first specify the HTTP Status Code (e.g. 200). Then, inside, provide a short description of when this response happens and content of the response #### 4. `openapi/schemas` As we have separated our request and response models, it is neccessary to have a combination file that gather all models. That's why in `openapi/index.yaml`, the schemas was reference to 1 `index.yaml` file in schemas folder. ##### a) `openapi/schemas/index.yaml` ```yaml! PetDetailsRequest: $ref: ./request/petDetails.yaml PetDetailsResponse: $ref: ./response/petDetails.yaml ``` ##### b) `openapi/schemas/request/petDetails.yaml` & `openapi/schemas/response/petDetails.yaml` ```yaml! type: object required: - name - photoUrls properties: id: type: integer format: int64 example: 10 name: type: string example: doggie category: $ref: '../category.yaml' photoUrls: type: array xml: wrapped: true items: type: string xml: name: photoUrl tags: type: array xml: wrapped: true items: $ref: '../tag.yaml' status: type: string description: pet status in the store enum: - available - pending - sold ``` - type: type of request - required: fields that are required in this request - properties: request field's type ![schemas folder](https://i.imgur.com/5NHxGoJ.png) **In this example, because response and request models are same, you should not write it twice.* #### 5. `openapi/parameters` Similar to schemas, we also need an index file to combine all parameters definition. ##### a) `openapi/parameters/index.yaml` ```yaml! PetId: $ref: ./petId.yaml ``` ##### b) `openapi/parameters/petId.yaml` ```yaml! name: petId in: path description: ID of pet to return required: true schema: type: integer format: int64 ``` - name: The name of the parameter. - in: Where is the parameter located? In the path, in the body, in a header, or somewhere else? - description: A short, user-friendly description of the parameter. - required: Is the parameter required or optional? - chema: includes: + type: The data type of the parameter. The common types are number and string. + format: is not compulsory #### 6. Generate interface for client side Well, as we split the specifications for better checking and modification. It's time to build those separate files into one. We can easily do that with just 1 command line. ```javascript! swagger-cli bundle index.yaml -o ./build.yaml -t yaml ``` - index.yaml is the input file that we want to build, which is located in `openapi/index.yaml` - /build.yaml is the build file, you can name it differently as you wish, or put it in build folder (like this /build/index.yaml) Now, we get 1 merged file. If you take a look, you'll see that it looks exactly like the one before we split. There are 2 ways to generate code: **Method #1: use cli** Make sure you have install the openapi cli: https://openapi-generator.tech/docs/installation/ Then, to generate the interface, use the command line as in the link and example below. https://openapi-generator.tech/docs/usage#generate Ex: ```javascript! openapi-generator-cli generate -i your_directory/openapi/build.yaml -g typescript-axios -o your_directory/openapi/output ``` Here, i generate code for typescript, but you can refer to below for the list of generators and their options that match your need. https://openapi-generator.tech/docs/generators **Method #2: use swagger editor** Go to https://editor.swagger.io/ then paste you build.yaml file in the editor. At the top, you can see the generator options, just select the one you need and it will generate and automatically download the output for you. *By using swagger editor, you can also view the api document you wrote in pretty ui and dont have to download swaggerUI ### III. Conclusion Swagger has been around for long and favored by many developers. It's not difficult to write api specification with Swagger and you can start right away with your current project. It's always good to know how to write a proper document that your team can refer to, so I hope this helps. <small> Published date: 2022-12-22 <br/> Also published <a href="https://medium.com/goalist-blog/how-to-write-rest-document-with-swagger-4109b30d6f6b">here</a>. </small>