手軽屋
ツール一覧

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必須フィールド用途
addpath / value指定パスに値を追加(配列は挿入、オブジェクトは新規キー)
removepath指定パスを削除
replacepath / value既存値を新しい値で置換
movepath / fromfrom を削除して path に追加
copypath / fromfrom の値を path に複製
testpath / 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を追加したのか」はテキスト差分だけでは判断しづらい。oasdiffopenapi-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) などが定番