iT邦幫忙

2024 iThome 鐵人賽

DAY 5
0
IT 管理

我要成為文件工程師── Web API 文件撰寫系列 第 5

[Day 05] OpenAPI:標準的 API 描述技術規範(四)

  • 分享至 

  • xImage
  •  

在多數的情境下,不會獨立存在一支 API,而是由一組 API 來對領域或資源進行存取,以會員服務來說,會有一組包含:註冊、異動、註銷、取得單筆、查詢多筆......等多支 API,才能讓應用端組合不同的 API 滿足需求,在這些 API 中,多數的會員資料結構是一致的。因此,就像在程式碼撰寫時會利用參考來減少重複一樣,撰寫 OpenAPI 規格時我們也可以透過收斂定義並參考引用,降低重複的內容。

首先,我們可以在 components.schemas 節點下,建立一個會員資料結構,命名為 Member 並定義其結構,範例如下:

components:
  schemas:
    Member:
      type: object
      properties:
        memberId:
          type: string
        name:
          type: string
        email:
          type: string
          format: email
        createdAt:
          type: string
          format: date-time

定義完就可以在取得單筆會員 API 和查詢多筆會員 API 的 Response 中,使用 $ref 參考 Member 結構,範例如下:

# 以上省略
paths:
  /members/{memberId}:
    get:
      summary: 取得單一會員資訊
      description: 查詢指定會員的資訊,若該會員不存在時回應 `404 Not Found`。
      operationId: getMember
      parameters:
        - name: memberId
          in: path
          required: true
          description: 會員 ID
          schema:
            type: string
      responses:
        '200':
          description: 成功取得會員資訊
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Member'
  /members:
    get:
      summary: 取得多筆會員資訊
      operationId: getMemberList
      parameters:
        - name: limit
          in: query
          description: 限制返回的會員數量
          schema:
            type: integer
            example: 10
        - name: offset
          in: query
          description: 分頁偏移量
          schema:
            type: integer
            example: 0
      responses:
        '200':
          description: 成功取得會員列表
          content:
            application/json:
              schema:
                type: object
                properties:
                  members:
                    type: array
                    items:
                      $ref: '#/components/schemas/Member'
components:
  schemas:
    Member:
      type: object
      properties:
        memberId:
          type: string
        name:
          type: string
        email:
          type: string
          format: email
        createdAt:
          type: string
          format: date-time

不只 schema,我們也可以在 components 下定義 parametersresponses,善加利用可以很有效減少重複的內容,例如定義 components.schemas.Error 搭配 components.responses.NotFoundResponse 和其他常見的錯誤回應就是不錯的選擇。

最後,為資料結構加上範例資料就可以讓文件更完整,我們可以使用example 節點替單個欄位分別設定,或在資料結構一次完整設定,範例如下:

# 單個欄位設定
components:
  schemas:
    Member:
      type: object
      properties:
        memberId:
          type: string
          example: "abc123"
        name:
          type: string
          example: "張三"
        email:
          type: string
          format: email
          example: "zhangsan@example.com"
        createdAt:
          type: string
          format: date-time
          example: "2024-01-01T00:00:00Z"

# 在 Member 一次設定
components:
  schemas:
    Member:
      type: object
      properties:
        memberId:
          type: string
        name:
          type: string
        email:
          type: string
          format: email
        createdAt:
          type: string
          format: date-time
      example:
        memberId: "abc123"
        name: "張三"
        email: "zhangsan@example.com"
        createdAt: "2024-01-01T00:00:00Z"

便可在 Redoc 右側看到我們設定的範例資料如下:

https://ithelp.ithome.com.tw/upload/images/20240918/20151137En7sfYtDQM.png

若有多種不同的範例組合,則可以利用 examples 節點,針對不同的場景提供不同的範例,例如 BadRequestError 有缺少必填欄位和資料格式不合法兩種場景,可以設定 examples 如下:

paths:
  /members:
    get:
      summary: 取得多筆會員資訊
      operationId: getMemberList
      parameters:
      # 省略
      responses:
        '200':
          description: 成功取得會員列表
          # 省略
        '400':
          description: 錯誤的請求
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BadRequestError'
              examples:
                InvalidInput:
                  $ref: '#/components/examples/InvalidInput'
                EmptyInput:
                  $ref: '#/components/examples/EmptyInput'
components:
  schemas:
    BadRequestError:
      type: object
      properties:
        errorCode:
          type: string
        message:
          type: string
  examples:
    InvalidInput:
      summary: 不合法的輸入參數
      value:
        errorCode: "INVALID_INPUT"
        message: "不合法的輸入參數"
    EmptyInput:
      summary: 輸入參數不得為空
      value:
        errorCode: "EMPTY_INPUT"
        message: "輸入參數不得為空"

這時,在 Redoc 右側可看到下拉選單出現不合法的輸入參數輸入參數不得為空兩種範例,如下圖所示:

https://ithelp.ithome.com.tw/upload/images/20240918/20151137ME1u9iQJGl.png

https://ithelp.ithome.com.tw/upload/images/20240918/201511375VxscKDsdF.png

至此,我們已經可以針對不同情境提供不同的範例,能滿足多數文件的需求。但若要描述的 API 資料結構和情境更加的複雜,出現多型的資料結構時又該如何是好呢?明天,將說明如何在 OpenAPI 中定義多型結構,完成 OpenAPI 基礎規格的最後一哩路。


上一篇
[Day 04] OpenAPI:標準的 API 描述技術規範(三)
下一篇
[Day 06] OpenAPI:標準的 API 描述技術規範(五)
系列文
我要成為文件工程師── Web API 文件撰寫12
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言