JSONPath か JSON Pointer か
要点:JSON Pointer はキーとして保存できる一意の住所で、JSONPath はクエリ言語です。誤って使うと設定更新が壊れるか、壊れた JSONPath を再発明することになります。

要点:1 ノードの住所を読み、書き、保存する必要があるとき(/server/cors/0 など)は JSON Pointer を使い、条件でノードの集合を選択する必要があるときは JSONPath を使いましょう。永続化するパスは常に Pointer で、式にしてはなりません。
必要なのが 1 ノードか、その集合かを問います。
一つの表で
| JSON Pointer | JSONPath | |
|---|---|---|
| 性質 | 一意の住所 | クエリ式 |
| 構文 | /a/b/0 |
$.a.b[0]、$..price |
| 結果 | ちょうど 1 ノード、またはなし | ゼロ以上のノード |
| キーとして保存可能 | 可能。文字列が同一性 | 不可。多数に一致しうる |
| 標準 | RFC 6901 | RFC 9535(2024 年確定) |
JSON Pointer
/server/host -> "127.0.0.1"
/server/cors/0 -> "https://a.com"
/ -> 文書全体
/ や ~ を含むキーはエスケープします。~ は ~0、/ は ~1。価値は決定性です。住所が文字列なので、データベース列、ログ行、設定キーに収まります。JSON Patch(RFC 6902)はすべての操作をこの方法で指定します。
JSONPath
$.store.book[*].author
$..price
$.store.book[?(@.price < 10)]
SQL の WHERE に近いものです。同じ式がデータに応じてゼロ、一つ、百のノードを返します。
二つの失敗モード
JSONPath を設定キーとして使う。 $.server.port を保存し、ある日構造が配列になります。式は複数のポートに一致し、更新ロジックはどれを選ぶかの手段を失います。
選択に Pointer を使う。 「価格が 10 未満のすべてのノードを探す」はポインタでは不可能です。自分でループを書くことは、部分的な JSONPath を作ることになります。
実際のシステムはどう分担するか
- 設定の読み取り、フィールド更新、パッチ:Pointer。固定で監査可能
- データ探索、一括抽出、レポート:JSONPath。表現力を優先
- 永続化するものすべて:Pointer のみ。式は決して使わない
FAQ
JSON Pointer と JSONPath はどう選べばよいですか?
必要なのが 1 ノードか集合かを問います。特定の 1 ノードを読み書きし、その住所をキーとして保存するには JSON Pointer を使います。ポインタは /server/cors/0 のように一意だからです。条件でノードを選択するには JSONPath を使います。たとえば $.store.book[?(@.price < 10)]。
JSONPath 式を設定キーとして使えないのはなぜですか?
式が複数のノードに一致しうるからです。$.server.port を保存し、ある日構造が配列になれば、式は複数のポートに一致し、更新ロジックはどれを変えるか決められません。永続化や監査が必要なものには Pointer が必要です。
JSON Pointer は条件でノードをフィルタできますか?
いいえ。ポインタは固定のパスをたどるだけで、どのノードが存在するかを知る手段がありません。価格が 10 未満のすべてのノードを選ぶことは不可能です。そのループを自分で書くことは、部分的な JSONPath を作ることになります。