本文へスキップ

OpenAPIの差分比較

OpenAPI Diff

2つのOpenAPI文書を比べ、互換性を壊す変更と足しただけの変更を分けて示します。

OpenAPIの文書の2つの版を比べ、変更を破壊的なものと追加だけのものに分けます。使っている規則はページに書いてあります。古い文書が受け付けていたリクエストがいまは拒否されうるようになったとき、あるいは約束していたレスポンスが、既存のクライアントにはもう扱えないものになったとき、その変更は破壊的です。

🔒 ブラウザの中だけで動きますopenapidiffapibreaking-change

以前の文書

以前のバージョンを置く

このタブの中だけで読みます。

新しい文書

新しいバージョンを置く

このタブの中だけで読みます。

非互換

8

追加・補完

7

判定

メジャーバージョンを上げる必要あり

表示

GET /pets

  • 非互換`in: query` のパラメータ `limit` が必須になりました。
  • 追加`in: query` の任意パラメータ `sort` が追加されました。
  • 変更概要か説明が変わりました。

GET /pets · responses["200"].content["application/json"]

  • 非互換`[].id`の型が integer から string に変わりました。
  • 非互換プロパティ `[].name` が任意になりました。
  • 非互換`[].status`の enum に "pending" が増えました。
  • 追加任意のプロパティ `[].owner` が追加されました。

GET /pets/{petId} · responses["200"].content["application/json"]

  • 非互換`id`の型が integer から string に変わりました。
  • 非互換プロパティ `name` が任意になりました。
  • 非互換`status`の enum に "pending" が増えました。
  • 追加任意のプロパティ `owner` が追加されました。

GET /pets/{petId}

  • 非互換`404` のレスポンスが消えました。

DELETE /pets/{petId}

  • 追加操作が追加されました。

components.schemas.Owner

  • 追加スキーマが追加されました。

info.version

  • 変更`1.0.0` → `2.0.0`

何をもって非互換とするか

一文で言えば、以前の文書が受け付けていたリクエストが拒まれうる、あるいは以前の文書が約束したレスポンスを既存のクライアントが扱えなくなる、ということです。したがって、経路・操作・レスポンスコード・メディアタイプ・レスポンスプロパティの削除、必須パラメータや必須のリクエストプロパティの追加、任意→必須、型の変更、リクエスト enum の値の削除、レスポンス enum の値の追加(クライアントの switch に case がありません)、レスポンスプロパティの必須→任意は非互換です。逆向きの変更と、説明・タグ・operationId・deprecated の表示は互換です。

  • · スキーマは文書内の $ref を辿ったうえで比べるので、コンポーネント名を変えただけでは変更になりません。経路パラメータも名前ではなく位置で対応づけます。
  • · oneOf·anyOf·not の中身は丸ごと比べ、違えば非互換として報告します。中身について推論はしません。
  • · 別のファイルを指す $ref は辿りません。先にファイルを1つにまとめてください。

文書ひとつを点検するなら OpenAPI 点検をどうぞ。

使い方

  1. 古い文書と新しい文書を並べます

    どちらもJSONでもYAMLでも構いません。両方このタブの中でパースするので、まだ公開していない仕様が機械の外に出ることはありません。

  2. 判定を読みます

    破壊的な変更の数、追加だけの変更の数、そしてそれがバージョン番号にとって何を意味するのか。メジャーを上げるのか、マイナーを上げるのか、契約が変わっていないので何もしなくてよいのか、です。

  3. 破壊的なものだけに絞って読みます

    操作ごとにまとめられ、それぞれに何が変わったのかが付きます。Markdownでのコピーは、プルリクエストの説明に収まる形にしてあります。

よくある質問

レスポンスの列挙に値を足すことが破壊的なのはなぜですか

既存のクライアントに、その値のための分岐が無いからです。*リクエスト*の列挙に足すのは安全です。サーバーが前より多くを受け付けるようになるだけだからです。レスポンスの列挙に足すと、聞かされていなかったものをクライアントに送ることになります。向きが、それを決めます。

コンポーネントの名前を変えたのに、変更が無いと報告されます

そのとおりです。スキーマは`$ref`をたどったあとで比べるので、形が同じままの改名は同じ契約です。`components`の中の名前は内部のもので、クライアントが見るのは解決されたあとの形です。

レスポンスの必須プロパティを任意にすることが、本当に破壊的なのですか

クライアントの側から見れば、そうです。そのフィールドは常にあると約束されていて、コードは条件を付けずに読んでいます。任意にするということは、サーバーがそれを省けるようになるということです。必須と任意は、リクエストとレスポンスのあいだで向きが入れ替わります。そこが、みなが逆に取るところです。

`oneOf`や`anyOf`はどう扱われますか

全体として比べ、少しでも違えば破壊的として報告します。ある合併型がもう一方の上位集合かどうかを推論するのは、ここでは意図的に手を出さない判定の手続きです。退けられる偽の「破壊的」のほうが、退けられない偽の「安全」よりましだからです。

ここから渡せます

次の一手

このツールが出したものをそのまま受け取れる道具です。