OpenAPI Diff

所謂 OpenAPI 對比,就是比較同一 API 規範的兩個版本——舊合約與新合約——並報告到底變了什麼:端點被刪除、參數變成必填、欄位類型發生變化、列舉值消失。在下方載入或貼上兩份規範,本頁面會把每一項變更分類為破壞性或非破壞性,讓你在供應商升級或自己的版本發布進入生產之前先作出判斷。兩個檔案都在本頁面、你的裝置上剖析——不會上傳任何內容,這很重要,因為規範裡往往描述了你不想放在別人伺服器上的內部端點。不熟悉這些術語?配套文章 破壞性 API 變更詳解 定義了這裡用到的每一個概念。

最後更新:

舊規範(用戶端今天正在使用的合約)

將檔案拖到此面板任意位置、選擇檔案,或貼上文字。剖析在本機進行;不會有任何內容離開這台裝置。

新規範(候選合約)

將檔案拖到此面板任意位置、選擇檔案,或貼上文字。剖析在本機進行;不會有任何內容離開這台裝置。

這個對比工具檢查什麼——以及「破壞性」到底是什麼意思

一項變更之所以是破壞性的,是因為一個嚴格按舊規範寫對的用戶端,不改自己一行程式碼,就可能在新規範下失敗。頁面上的每一個判斷都由這個定義驅動。刪除路徑或操作是破壞性的,因為現有的呼叫無處可去。刪除回應狀態碼——尤其是 2xx——是破壞性的,因為用戶端的錯誤處理正是圍繞舊的狀態碼集合編寫的。新增一個必填參數或必填的請求屬性是破壞性的,因為昨天的合法請求會突然被拒絕。改變欄位的類型或格式是破壞性的,因為剖析器、驗證器和生成的 SDK 都按宣告的類型工作。移除列舉值是破壞性的,因為用戶端可能仍會傳送它,或者儲存著無法再解釋的資料。其餘一切——新端點、可選參數、新的回應欄位、新的列舉值、新的狀態碼——都被報告為非破壞性:舊用戶端繼續可用,哪怕它暫時還用不上新能力。

比較是結構層面的,不是文字層面的。在比較之前,兩份文件都會被正規化為同一個模型:每條路徑和每個操作、按名稱與位置索引的參數、請求正文與每個回應都被歸約為一個模式簽名——由類型、格式、屬性名、必填清單和列舉值遞迴構建的確定性摘要,本地 $ref 引用會被展開。正因如此,調整鍵的順序、重排空白或重寫所有描述文字都會得到一個空的對比結果:這些都不改變合約。也正因如此,埋在被引用模式三層深處的一處變更仍然會被找到——簽名展開的是引用本身,而不是僅僅比較它的名字。

這裡接受兩種輸入形態,因為生態裡兩種都有人發布:先按 JSON 嘗試剖析,失敗時再按 YAML 剖析——大多數手寫的 OpenAPI 文件用的正是 YAML。Swagger 2.0 文件同樣可用,包括它的 in: body 參數和每個回應自帶的模式。這裡刻意沒有線上抓取、也沒有上傳:像處理 HAR 擷取檔案 一樣貼上文件或拖入檔案即可,而且對比是在你按下按鈕時才執行——而不是每次按鍵都執行——所以貼上兩份很大的規範也不會卡頓。

把結果當作發布門檻來用,而不是裝飾。在審查中,破壞性清單就是議程:每一項都需要修復、提升版本號、給出棄用窗口,或者留下一份「這次破壞是有意為之且已通知」的書面決定。非破壞性清單就是變更日誌的草稿。把對比結果匯出為 JSON,可以把這份決定歸檔在版本旁邊;可複製的摘要可以直接放進拉取請求——這與對待 webhook 合約變更 是同一套紀律:一份被悄悄改動的負載會同時破壞每一個訂閱方。

誠實的限制,明確說出來。這個對比工具比較的是宣告過的合約:它看不見規範沒有宣告的行為,例如欄位類型不變但含義變了、新增的業務規則、更緊的限流,或者用戶端(不明智地)在剖析的錯誤訊息文字。工具會跟隨本地引用並在有限深度內比較模式,因此病態的深層嵌套或互相遞迴的模式會被摘要化,而不是無限展開下去。而且,零破壞性變更的對比結果並不能保證升級一定安全——它證明的是文件化的合約沒有變,這恰恰是部署之前值得擁有的證據。

本頁據以評判的分類表

刪除路徑或操作破壞性。對一個已不存在的端點的呼叫會直接失敗;沒有任何相容方式能讓舊用戶端繼續對著它工作。
刪除回應狀態碼破壞性。用戶端的重試、錯誤處理和監控邏輯都是圍繞宣告過的狀態碼集合編寫的;丟失一個 2xx 是其中最嚴重的形式。
參數變為必填 / 新增必填欄位破壞性。在舊規範下合法的請求會被新規範拒絕,因此每個現有用戶端都必須先做出修改才能呼叫該端點。
類型或格式變更破壞性。剖析器、驗證器和生成的 SDK 都是按宣告的類型構建的;integer 改成 string(或 int32 改成 int64)會破壞嚴格的用戶端,哪怕線上值看起來很相似。
刪除屬性(請求或回應)破壞性。用戶端傳送的請求屬性會被忽略或拒絕;用戶端讀取的回應屬性會在它的程式碼裡變成空值或缺失。
移除列舉值破壞性。用戶端可能仍會傳送被移除的值,或者儲存著使用該值的資料。新增的列舉值是非破壞性的,會被單獨報告。
新增內容非破壞性。新的路徑、操作、可選參數、可選的請求屬性、回應屬性、回應狀態碼和列舉值,永遠不會讓一次先前合法的互動失效。

常見問題

我的規範檔案會被上傳到任何地方嗎?

不會。兩份文件都在本頁面、你的裝置上剖析和比較;比較過程不會發出任何網路請求,也不會儲存任何內容。這是一條刻意定下的規則:規範就是一份 API 的地圖——包括內部的和未公開文件的端點——一個要求你先上傳它才能對比的工具,收集的恰恰是你應該保密的那張地圖。

接受哪些格式?

OpenAPI 3.x 和 Swagger 2.0,JSON 或 YAML 均可。文字先按 JSON 嘗試,失敗時按 YAML 剖析。文件必須帶有 paths 物件才會被識別為規範;其他內容會被報告為「不是規範」,而不是悄悄給出一個空的對比結果。

這裡什麼算破壞性變更?

任何可能讓一個寫對的舊用戶端失敗的變更:刪除路徑、操作或回應狀態碼;參數或請求屬性變為必填;類型或格式變更;刪除請求或回應屬性;以及移除列舉值。新增任何可選內容都是非破壞性的。描述、標題和格式變化會被完全忽略——它們不是合約變更。

被引用的模式如何處理?

構建簽名時,#/components/schemas/Pet 這類本地引用(或 Swagger 2.0 中的 #/definitions/Pet)會被解析,因此一份共用模式內部的變更會在每個使用它的操作上被報告。解析有深度上限且能安全處理循環,遞迴模式不會讓比較卡死。

我可以歸檔或分享結果嗎?

可以。下載按鈕把完整的對比結果匯出為 JSON——摘要計數加上每一項變更的嚴重級別、種類、路徑、方法和結構化細節;複製按鈕生成適合放進拉取請求或發布說明的純文字摘要。兩者都是在本機從你剛執行的對比結果生成的。