Tools mentioned in this article
Open the browser-based tool while you read and try the workflow immediately.
巢狀結構定義的麻煩事
OpenAPI Specification(OAS) 是描述 RESTful API 介面的標準規範,與程式語言無關(過去稱為「Swagger」)。它是自動產生文件、產生客戶端 SDK、建立 Mock 伺服器的基礎。
手動撰寫請求/回應主體的「Schema」——把層層嵌套的物件對應到 type/properties/required/items——既耗時又容易出錯。
JSON 轉 OpenAPI 生成工具 只要輸入一份範例 JSON payload,就能自動產生 components/schemas 定義。

型別推導的原理
產生器會逐一走訪 JSON 的每個值,將其對應到 OpenAPI 型別。
private static inferSchema(value: unknown): OpenApiSchema {
if (value === null) return { type: 'null' };
if (Array.isArray(value)) {
// 若所有元素共用同一個 schema 就直接使用,否則包成 oneOf
const itemSchemas = this.mergeSchemas(value.map((item) => this.inferSchema(item)));
const items = itemSchemas.length === 1 ? itemSchemas[0] : { oneOf: itemSchemas };
return { type: 'array', items };
}
if (typeof value === 'number') {
return { type: Number.isInteger(value) ? 'integer' : 'number' }; // 區分整數與浮點數
}
// 物件會遞迴展開成 properties,且所有存在的鍵都視為必要欄位
}
這裡有兩個重點:
- 數字用
Number.isInteger分類——30會變成integer,30.5則變成number。 - 陣列中若混雜不同型別,會轉成
oneOf。像["admin", 1, true]這樣的陣列,會產生items: { oneOf: [{type: string}, {type: integer}, {type: boolean}] }。
日期字串的自動偵測
符合 ISO 8601 格式的字串,會用正規表示式比對,自動加上 format: date-time。
if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z$/.test(stringValue)) {
return { type: 'string', format: 'date-time' };
}
像 2026-01-15T12:00:00Z 這樣的值會被偵測到,但只有日期的字串(2026-01-15)或帶時區偏移的值(+09:00)不符合這個正規表示式,因此生成後需要手動補上 format: date。
使用方法與輸出範例
{
"id": 123,
"name": "Yamada Taro",
"email": "taro@example.com",
"roles": ["admin", "editor"],
"profile": {
"createdAt": "2026-01-15T12:00:00Z",
"isActive": true
}
}
從這份 JSON 可以推導出:id 為 integer、name/email 為 string、roles 為 array、profile 為嵌套的 object,createdAt 則是帶有 format: date-time 的 string。
- 執行 API,取得實際的 JSON 資料
- 貼到 JSON 轉 OpenAPI 生成工具
- 幾秒內就能得到
components/schemas格式的定義 - 把生成的定義整合進您的
openapi.yaml
只要存在的鍵就會變成「必要」——這是刻意的設計
在目前的實作中,範例 JSON 裡存在的鍵,全部都會被標記為 required。
for (const [key, val] of Object.entries(value)) {
properties[key] = this.inferSchema(val);
required.push(key); // 只要存在的鍵,一律視為必要
}
這是刻意簡化的結果:光憑一份範例 JSON,沒辦法判斷某個鍵究竟是真的必要,還是那次剛好有值而已。如果您實際的 API 有可省略的欄位,請在生成後手動把它們從 required 中移除。
生成後務必檢查的項目
從 JSON 產生的 OpenAPI 結構定義,應該視為「精確度較高的草稿」,而非最終定案。
- 把實際上可以省略的欄位從
required中移除 - 確認 ID、金額、數量等數值欄位該用
integer還是number - 確認日期字串是否加上了您期望的
format(自動偵測只涵蓋date-time) - 檢查陣列是否只採樣到空陣列(空陣列會變成
items: {}) - 補上
description與example,讓使用者理解各欄位的意義
遵循 OpenAPI 3.1
產生的結構定義以 OpenAPI 3.1.0 為目標。不同於 OpenAPI 3.0 的 nullable: true,這裡採用 3.1 標準化的 type: "null"(或聯合型別)寫法。如果您既有的專案是統一使用 OpenAPI 3.0,匯入輸出結果前可能需要轉換這個差異。
常見問題
也能用在 Swagger 嗎?
可以。OpenAPI 過去曾稱為 Swagger,現在仍常聽到「Swagger schema」「Swagger UI」這類說法。生成的結構定義可以直接用在 Swagger UI 等文件工具上。
請求主體與回應主體都能用嗎?
可以。POST/PUT 請求的 JSON、GET 回應的 JSON、Webhook 的 payload,只要是結構明確的 JSON,都能當作結構定義的起點。
陣列中的型別不一致時會怎麼處理?
會用 oneOf 把各種不同的型別列出來。至於要統一型別,還是就維持 oneOf 的形式,屬於 API 設計上的判斷。
需要在意 OpenAPI 3.0 與 3.1 的差異嗎?
如果您既有的專案統一使用 OpenAPI 3.0,匯入輸出結果前,請先確認 nullable 與 type: null 的處理方式。若是新專案或內部工具用途,直接採用 OpenAPI 3.1 的表示法通常沒有問題。
總結
- 型別推導是遞迴走訪每個值:數字分成整數/浮點數,陣列中型別混雜會轉成
oneOf - 日期偵測以正規表示式為基礎,只涵蓋
date-time格式,其餘需要手動調整 - 範例中存在的鍵一律會變成
required,可省略的欄位請在生成後自行移除 - 輸出以 OpenAPI 3.1.0 為準
自動生成終究只是草稿。生成後補上 description 與 example,才能變成團隊成員與 API 使用者都樂於閱讀的文件。