OpenAPI Diff

OpenAPIの差分比較とは、API仕様の2つのバージョン——現在の契約と新しい契約——を比較し、実際に何が変わったかを報告することです:削除されたエンドポイント、必須になったパラメータ、型が変わったフィールド、消えた列挙値。下に両方の仕様を読み込むか貼り付けてください。このページはすべての変更を破壊的か非破壊的かに分類します。ベンダーのアップグレードや自分のリリースが本番に届く前に判断できます。両ファイルはこのページ上、あなたのデバイスで解析されます——何もアップロードされません。仕様には他人のサーバーに置きたくない内部エンドポイントが書かれていることが多いため、これは重要な点です。用語に不慣れですか?コンパニオン記事破壊的API変更の解説で、ここで使う用語をすべて定義しています。

最終更新:

旧仕様(クライアントが今日使っている契約)

このパネルの任意の場所にファイルをドロップするか、ファイルを選ぶか、テキストを貼り付けてください。解析はローカルで行われ、何もこのデバイスから出ません。

新仕様(候補の契約)

このパネルの任意の場所にファイルをドロップするか、ファイルを選ぶか、テキストを貼り付けてください。解析はローカルで行われ、何もこのデバイスから出ません。

この比較ツールがチェックすること——そして「破壊的」の本当の意味

変更が破壊的であるのは、旧仕様に対して正しく書かれたクライアントが、自分のコードを1行も変えずに新仕様で失敗しうるときです。このページのすべての判定はこの定義に基づきます。パスや操作の削除は破壊的です。既存の呼び出しの行き先がなくなるからです。レスポンスステータス——とりわけ2xx——の削除は破壊的です。クライアントのエラー処理は旧ステータスの集合を前提に書かれているからです。必須パラメータや必須のリクエストプロパティの追加は破壊的です。昨日まで有効だったリクエストが突然拒否されるからです。フィールドの型やフォーマットの変更は破壊的です。パーサ、バリデータ、生成されるSDKはすべて宣言された型を前提にしているからです。列挙値の削除は破壊的です。クライアントは今もその値を送るかもしれず、解釈できなくなったデータを保持しているかもしれないからです。それ以外——新しいエンドポイント、任意パラメータ、新しいレスポンスフィールド、新しい列挙値、新しいステータスコード——はすべて非破壊的として報告されます。古いクライアントは動き続けます。新しい機能をまだ使えなくてもです。

比較はテキストではなく構造で行われます。両ドキュメントは比較の前に同じモデルへ正規化されます。各パスと操作、その名前と場所で索引付けされたパラメータ、リクエストボディと各レスポンスは、スキーマシグネチャへと還元されます。これは型、フォーマット、プロパティ名、必須リスト、列挙値から再帰的に構築される決定的な要約で、ローカルの $ref 参照は解決されます。だからこそ、キーの順序を変えたり、空白を整形し直したり、すべての説明文を書き換えたりしても、差分は空になります。それらは契約を変えないからです。そして、参照されるスキーマの3階層深くに埋もれた変更も見つかります。シグネチャは参照の名前を比較するのではなく、参照を展開するからです。

エコシステムが両方を公開しているため、入力形式は2種類を受け付けます。まずJSONとして試し、失敗した場合はYAMLとして解析します。手書きのOpenAPIドキュメントの多くがYAMLを使っています。Swagger 2.0のドキュメントも動作します。in: body パラメータやレスポンスごとのスキーマも含みます。意図的に、ライブ取得もアップロードもありません。HARキャプチャと同じようにドキュメントを貼り付けるかファイルをドロップしてください。比較はキーを押すたびではなく、ボタンを押したときに実行されるため、貼り付けた2つの大きな仕様でも応答性が保たれます。

結果は飾りではなく、リリースのゲートとして使ってください。レビューでは、破壊的リストが議題そのものです。各エントリには、修正、バージョン番号の引き上げ、非推奨期間の設定、あるいは「破壊は意図的で周知済み」という書面の決定のいずれかが必要です。非破壊的リストは変更履歴の下書きです。差分をJSONでエクスポートすれば、その決定をリリースの横に保管でき、コピーできる要約はプルリクエストにそのまま入ります。これは、ペイロードが静かに変更されるとすべての購読者が同時に壊れる webhook の契約変更に適用するのと同じ規律です。

正直な限界を明言します。この比較ツールは宣言された契約を比較します。仕様が宣言していない振る舞いは見えません。型は同じでも意味が変わったフィールド、新しい業務ルール、より厳しいレート制限、クライアントが(賢明とは言えず)解析していたエラーメッセージなどです。ローカル参照をたどり、有限の深さまでスキーマを比較するため、病的に深く入れ子になったスキーマや相互再帰スキーマは、無限に展開されるのではなく要約されます。そして、破壊的変更ゼロの差分は、アップグレードが安全だという約束ではありません。文書化された契約が保たれたという証拠であり、それこそがデプロイ前に持つ価値のある証拠なのです。

このページが判定に使う分類表

パスまたは操作の削除破壊的。存在しなくなったエンドポイントへの呼び出しは即座に失敗します。古いクライアントをそのまま動作させ続ける互換的な方法はありません。
レスポンスステータスの削除破壊的。クライアントのリトライ、エラー処理、監視のロジックは、宣言されたステータスの集合に対して書かれます。2xxを失うことは、その最も深刻な形です。
パラメータが必須化/必須フィールドの追加破壊的。旧仕様で有効だったリクエストが新仕様に拒否されるため、既存のクライアントはすべて、エンドポイントを呼び出せるようになる前に変更しなければなりません。
型またはフォーマットの変更破壊的。パーサ、バリデータ、生成されるSDKは宣言された型から構築されます。integerからstringへ(またはint32からint64へ)の変更は、ワイヤ上の値が似て見えても、厳格なクライアントを壊します。
プロパティの削除(リクエストまたはレスポンス)破壊的。クライアントが送るリクエストプロパティは無視されるか拒否され、クライアントが読むレスポンスプロパティはそのコードの中でnullになるか欠落します。
列挙値の削除破壊的。クライアントは削除された値を今も送るかもしれず、その値を使った保存データを持っているかもしれません。追加された列挙値は非破壊的で、別々に報告されます。
追加非破壊的。新しいパス、操作、任意パラメータ、任意のリクエストプロパティ、レスポンスプロパティ、レスポンスステータス、列挙値は、以前は有効だったやり取りを無効にすることは決してありません。

よくある質問

仕様ファイルがどこかにアップロードされることはありますか?

ありません。両ドキュメントはこのページ上、あなたのデバイスで解析と比較されます。比較によってネットワークリクエストが発生することはなく、何も保存されません。これは意図的なルールです。仕様はあなたのAPIの地図であり、内部や未文書化のエンドポイントも含みます。比較するためにアップロードを求めるツールは、まさに非公開にすべきその地図を収集することになるからです。

どの形式を受け付けますか?

OpenAPI 3.xとSwagger 2.0で、JSONまたはYAMLです。テキストはまずJSONとして試され、失敗した場合はYAMLとして解析されます。ドキュメントが仕様として認識されるには paths オブジェクトが必要です。それ以外は、静かに空の差分を出すのではなく、「仕様ではない」と報告されます。

ここでは何が破壊的変更に当たりますか?

正しく書かれた古いクライアントを失敗させうるものすべてです。パス、操作、レスポンスステータスの削除。必須になったパラメータやリクエストプロパティ。型やフォーマットの変更。リクエストまたはレスポンスプロパティの削除。列挙値の削除です。任意のものを追加することは非破壊的です。説明、タイトル、フォーマットの変更は完全に無視されます——それらは契約の変更ではないからです。

参照されるスキーマはどう扱われますか?

#/components/schemas/Pet のようなローカル参照(Swagger 2.0では #/definitions/Pet)は、シグネチャ構築時に解決されます。そのため、共有スキーマ内部の変更は、それを使うすべての操作で報告されます。解決には深さの上限があり、循環にも安全なので、再帰的なスキーマが比較を止めることはありません。

結果を保管したり共有したりできますか?

できます。ダウンロードボタンは差分全体をJSONでエクスポートします——要約のカウントに加え、深刻度、種類、パス、メソッド、構造化された詳細を持つすべての変更です。コピーボタンは、プルリクエストやリリースノート向けのプレーンテキストの要約を生成します。どちらも、今実行した比較からローカルで生成されます。