JSON Patch(RFC 6902)とAPI差分管理
最終更新:2026年6月16日/一次情報:IETF RFC 6902 (2013-04), RFC 6901, RFC 7396
JSON Patch は IETF が 2013年4月に発行した RFC 6902 で標準化された「JSON文書への変更操作を JSON で記述する」仕様だ。テキスト差分(unified format)が「人間が読むための差分」だとすれば、JSON Patch は「機械が適用するための差分」と言える。OpenAPI のスキーマ進化管理、Kubernetes のリソース更新、HTTP PATCH メソッドのリクエストボディなどで広く使われる。
6つの操作(op)
| op | 必須フィールド | 用途 |
|---|---|---|
add | path / value | 指定パスに値を追加(配列は挿入、オブジェクトは新規キー) |
remove | path | 指定パスを削除 |
replace | path / value | 既存値を新しい値で置換 |
move | path / from | from を削除して path に追加 |
copy | path / from | from の値を path に複製 |
test | path / value | 指定値と一致するか確認(不一致で全体失敗) |
path は RFC 6901 の JSON Pointer 記法で /items/0/name のようにスラッシュ区切りで指定する。配列の末尾追加は /items/-。~ は ~0、/ は ~1 にエスケープする。
具体例
変更前:
{ "user": { "name": "Tanaka", "age": 30 } }JSON Patch:
[
{ "op": "replace", "path": "/user/age", "value": 31 },
{ "op": "add", "path": "/user/email", "value": "tanaka@example.com" }
]適用後:
{ "user": { "name": "Tanaka", "age": 31, "email": "tanaka@example.com" } }RFC 7396 JSON Merge Patch との違い
RFC 7396 の JSON Merge Patch(application/merge-patch+json)は「差分そのものを JSON 構造で表現する」より素朴な方式だ。変更後の JSON を部分的に書いて送り、null は「削除」を意味する。シンプルで読みやすいが、配列の一部要素だけ変更する操作が表現できない(配列はまるごと置換)。一方 RFC 6902 は配列の挿入・削除も細かく表現できる。HTTP PATCH を実装する際は、どちらのメディアタイプを受け付けるかを Content-Type で明示する必要がある。
OpenAPIスキーマの差分管理
OpenAPI(旧Swagger)の YAML ファイルを Git で管理していると、PR ごとにスキーマの差分が unified format で出る。けれど「フィールド名を変えたのか、追加したのか」「型を変えたのか、enumを追加したのか」はテキスト差分だけでは判断しづらい。oasdiff や openapi-diff のような専用ツールは内部的に JSON Patch ライクな構造的差分を出してくれる。後方互換性のチェック(破壊的変更の検出)にはこちらが必須だ。
Kubernetes の strategic merge patch
Kubernetes は application/strategic-merge-patch+json という独自のメディアタイプを持つ。基本は JSON Merge Patch だが、リソース定義の patchStrategy アノテーションで「配列要素をマージするキー」を指定できる。kubectl apply は内部的にこれを使って「同じコンテナ名のリソースは置換、新規は追加」を実現している。kubectl patch --type=json なら RFC 6902 が使える。
実務での注意点
test操作で楽観的ロック相当を実現できるが、ETag ベースの If-Match の方が一般的- JSON Pointer のエスケープ(
~0/~1)は忘れがち。テストで担保する - 大規模な差分は JSON Patch でも読みづらい。人間レビュー用には unified diff を併用
- クライアント実装ライブラリは fast-json-patch (JS) / python-json-patch / jsonpatch (Go) などが定番