Purpose of This Post
We can create an OpenAPI document using Swagger. In this post I would like to try to give a short explanation of how to create an API document using Swagger.
If you want to know the final outcome first, please take a look at Summary first.
About OpenAPI
OpenAPI Specification (formerly Swagger Specification) is an API description format for REST APIs.
(Sited from https://swagger.io/docs/specification/about/.)
Preparation
First, open Swagger Editor (https://editor.swagger.io). You will see the page like this:
Second, clear the YAML content.
Let's Start with a Simple Example
Here is a simple example that just contains info and servers of this API:
openapi: 3.0.3
info:
version: 1.0.0
title: Simple Todo API
description: This is a simple API for todo notes
servers:
- url: https://example.com/v1
paths: {}
Let me explain it briefly. The openapi
specifies the version of the OpenAPI specification. This openapi
field is required for each OpenAPI document.
The info
object contains two required fields, version
and title
. The version
specifies the version of the OpenAPI document (not OpenAPI Specification version nor the API implementation version) and the title
specifies the title of the API. The info
object also contains description
field, which is optional. It is used for a short description of the API.
The servers
array specifies server URLs for API calls. In the above example, the server URL is https://example.com/v1
.
At this point, our OpenAPI document is like:
Let's Add Resource Paths
You may have already noticed that paths
object was left as empty in previous section. Let's define some endpoints in this section.
Suppose that a client can:
- get all notes by sending a GET request to
/notes
endpoint. - get a note by note ID by sending a GET request to
/notes/{noteId}
endpoint where{noteId}
is a note ID. - create a note by sending a POST request to
/notes
endpoint.
Also suppose that note object is represented as the following JSON object:
{
"id": 1, // integer
"title": "sample title", // string
"content": "sample content" // string
}
Tags
Before defining endpoints, we will define a tag in tags
like:
tags:
- name: notes
description: Everything about your notes
The tags
object is not required, but by defining tags we can group our endpoints.
At this point, our OpenAPI document is like:
Path Item
First let's define the /notes
and the GET method for this endpoint. Replace the paths
object with:
paths:
/notes: # A relative path to an individual endpoint.
get: # GET method on this path.
tags:
- notes
summary: Find all notes
description: Returns all notes
responses:
'200': # HTTP Status Code
description: Successful operation
content: {} # Described later.
We haven't yet defined the response body of a GET request to /notes
endpoint, so we will define it. Modify paths
to:
paths:
/notes:
get:
tags:
- notes
summary: Find all notes
description: Returns all notes
responses:
'200':
description: Successful operation
content:
application/json: # media type
schema:
type: array
items:
type: object
properties:
id:
type: integer
format: int64
title:
type: string
example: Sample title
content:
type: string
example: Sample content
Look at the schema
. Its structure corresponds to that of a list of note objects defined before:
[
{
"id": 1, // integer
"title": "sample title", // string
"content": "sample content" // string
}
]
That's it for our first path item. This definition indicates that if a client calls GET https://example.com/v1/notes
, he/she will receive 200 HTTP status code with a list of notes like:
[
{
"id": 1,
"title": "title 1",
"content": "content 1"
},
{
"id": 2,
"title": "title 2",
"content": "content 2"
}
]
At this point, our OpenAPI document is like:
Parameters
Next let's define the /notes/{noteId}
and the GET method for this endpoint. Add the following to the paths
object:
/notes/{noteId}:
get:
tags:
- notes
summary: Find note by ID
description: Returns a single note
parameters: # You can define parameters here.
- name: noteId
in: path
required: true
description: ID of note to return
schema:
type: integer
format: int64
responses:
'200':
description: Successful operation
content:
application/json:
schema:
type: object
properties:
id:
type: integer
format: int64
title:
type: string
example: Sample title
content:
type: string
example: Sample content
'404':
description: Note not found
content:
application/json:
schema:
type: object
properties:
status:
type: integer
format: int32
message:
type: string
It's basically the same as the definition of GET method for /notes
. One of a difference is the existence of 404 HTTP status code response. We can use any HTTP status codes as property names.
Another important difference is the parameters
field. We can define parameters (such as path parameter, query parameter) in this parameters
field. Here is the part of the parameters
:
parameters:
- name: noteId
in: path # This is a path parameter.
required: true # This parameter is required.
description: ID of note to return
schema:
type: integer # This is an integer parameter.
format: int64
At this point, our OpenAPI document is like:
Components
As you may have noticed, we defined the note object twice. We can avoid defining the same object many times using the components
object. Let's define Note
and ApiResponse
and reuse them. Add the following components
object:
components:
schemas:
Note:
type: object
properties:
id:
type: integer
format: int64
title:
type: string
example: Sample title
content:
type: string
example: Sample content
ApiResponse:
type: object
properties:
status:
type: integer
format: int32
message:
type: string
Then modify the paths
object to:
paths:
/notes:
get:
tags:
- notes
summary: Find all notes
description: Returns all notes
responses:
'200':
description: Successful operation
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Note' # New
/notes/{noteId}:
get:
tags:
- notes
summary: Find note by ID
description: Returns a single note
parameters:
- name: noteId
in: path
required: true
description: ID of note to return
schema:
type: integer
format: int64
responses:
'200':
description: Successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/Note' # New
'404':
description: Note not found
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse' # New
At this point, our OpenAPI document is like:
Request Body
Finally let's add the POST method for /notes
endpoint. Add the following object to /notes
:
post: # POST method
tags:
- notes
summary: Add a new note
description: Tries to craete a new note and returns a message
requestBody: # We can define the request body here.
required: true
description: Note object that needs to be added
content:
application/json:
schema:
$ref: '#/components/schemas/Note'
responses:
'200':
description: Successfully added
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
'500':
description: Unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
Since this is a definition for POST method, post
is used.
Also, there is a new field, requestBody
. We can define the request body using the requestBody
field. Here is the part of requestBody
:
requestBody: # We can define the request body here.
required: true
description: Note object that needs to be added
content:
application/json:
schema:
$ref: '#/components/schemas/Note'
Now our OpenAPI document is like:
Summary
That's it. I made a short explanation of how to create an OpenAPI document using Swagger.
Following is the final outcome:
openapi: 3.0.3
info:
version: 1.0.0
title: Simple Todo API
description: This is a simple API for todo notes
servers:
- url: https://example.com/v1
tags:
- name: notes
description: Everything about your notes
paths:
/notes:
get:
tags:
- notes
summary: Find all notes
description: Returns all notes
responses:
'200':
description: Successful operation
content:
application/json: # media type
schema:
type: array
items:
$ref: '#/components/schemas/Note'
post: # POST method
tags:
- notes
summary: Add a new note
description: Tries to craete a new note and returns a message
requestBody: # We can define the request body here.
required: true
description: Note object that needs to be added
content:
application/json:
schema:
$ref: '#/components/schemas/Note'
responses:
'200':
description: Successfully added
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
'500':
description: Unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
/notes/{noteId}:
get:
tags:
- notes
summary: Find note by ID
description: Returns a single note
parameters:
- name: noteId
in: path
required: true
description: ID of note to return
schema:
type: integer
format: int64
responses:
'200':
description: Successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/Note'
'404':
description: Note not found
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
components:
schemas:
Note:
type: object
properties:
id:
type: integer
format: int64
title:
type: string
example: Sample title
content:
type: string
example: Sample content
ApiResponse:
type: object
properties:
status:
type: integer
format: int32
message:
type: string
Top comments (0)