ToolPal
光ファイバーケーブルを流れる輝くデータ

ブラウザでのJSONPath: 実際に使うパターンのための実用的なリファレンスとテスター

📷 Pixabay / Pexels

ブラウザでのJSONPath: 実際に使うパターンのための実用的なリファレンスとテスター

JSONPathクエリが期待通りに一致するか推測するのをやめましょう。フィルター、スライス、再帰下降演算子の実用的なガイド — 無料テスター付き。

D著者: Daniel Park2026年4月26日2分で読了

私はXMLがデフォルトで、XPathが誰もが学ぶクエリ言語だった時代を覚えているほど長くAPIで作業してきました。JSONPathはJSON相当のもので、何年も避けてきた後(JavaScriptを書けばいいから、ですよね?)、考えを改めました。JSONPathが唯一利用可能な言語である場所が多すぎます — Postman変数、AWS Step Functions、Kubernetesセレクター、Datadogフィルター — そして流暢になることは実際に時間を節約します。

このガイドは、私が始めたときに欲しかったリファレンスです。実際に本番で登場する構文、私に何時間も費やさせた落とし穴、そしてToolBox HubsのJSONPathテスターを使って、結果に影響する場所に貼り付ける前に式を確認する方法をカバーします。

JSONPathとは何か、簡単に

JSONPathはJSONドキュメントのクエリ言語です。$.store.book[*].authorのような式を渡すと、一致するすべての値を返します。$はルート、ドットとブラケットは構造内をナビゲートし、特殊な演算子はフィルター、スライス、再帰的トラバースを可能にします。

XMLでXPathを使ったことがあれば、メンタルモデルが直接転送されます。なければ、JavaScriptのドット表記のより強力なバージョンと考えてください — 「価格が10ドル未満のすべての本」や「ドキュメント内の任意の深さのすべての著者」を1行で表現できるものです。

誰もが使う正典的な例はStefan Goessnerの元記事から来ています:

{
  "store": {
    "book": [
      { "category": "fiction", "author": "Tolkien", "price": 22.99 },
      { "category": "reference", "author": "Rees", "price": 8.95 }
    ],
    "bicycle": { "color": "red", "price": 19.95 }
  }
}

$.store.book[*].author["Tolkien", "Rees"]を返します。$..price[22.99, 8.95, 19.95]を返します。$.store.book[?(@.price < 10)]は2番目のbookオブジェクトを返します。それがゲーム全体です。

90%の時間使う演算子

JSONPath演算子は数十あります。そのうち5つが、実際に書くもののほとんどをカバーします。

$ — ルート

すべてのJSONPath式は$で始まります。これはドキュメントのトップを参照します。技術的に省略できます(一部のライブラリは寛容です)が、明示的に書くと意図が明確になります。

.field — 子アクセス

標準のドット表記。$.users.0.emailはルートからusers配列を歩き、インデックス0を選び、emailを読みます。0がプロパティ名として機能することを除いてJavaScriptと同じです。

[n] — 配列インデックス

配列アクセスのためのブラケット表記、インデックスが動的な場合やフィールド名に特殊文字がある場合に便利です。$.users[0]$.users[-1](最後の項目)、$.users[0:3](0から3まで排他的なスライス)。

負のインデックスは末尾から数えます。$.users[-1]は最後のユーザーです。$.users[-3:]は最後の3つを返します。これはすべての実装でサポートされているわけではありません — RFC 9535は標準化していますが、依存している場合はライブラリを確認してください。

[*] — ワイルドカード

配列内のすべての項目またはオブジェクト内のすべての値に一致します。$.users[*].emailはすべてのユーザーのメールを返します。$.config.*はconfigオブジェクトのすべての値を返します。プロパティアクセスと組み合わせると、これが一般的な構造をフラット化する方法です。

..field — 再帰下降

最も強力な演算子で、私が最もよく使うものです。$..priceはネストの深さに関係なく、ドキュメント内のあらゆる場所のすべてのpriceフィールドを見つけます。正確な構造を知らないか気にしないときに便利です。

下降はパスを気にしません — パターンに一致するすべてを見つけるだけです。これがアドホックなデータ探索(「このレスポンスにユーザーIDは含まれていますか?」)に最適で、データが異なるコンテキストで同じキー名を持つ場合(ユーザーのnameフィールドとロールのnameフィールドの両方が$..nameに一致する)に危険にする理由です。

フィルター: 人々が詰まる場所

フィルター式は[?(...)]として書かれ、内容は配列内の各項目に対して評価されるブール式です。フィルター内で、@は現在の項目を指します。

$.store.book[?(@.price < 10)]
$.users[?(@.role == 'admin')]
$.events[?(@.timestamp > 1700000000)]

@が人々をつまずかせる部分です。これはforEachthisまたは現在の項目に相当します。それなしでは、フィルターはどのフィールドも参照できません — [?(price < 10)]priceが未定義なので動作しません。エンジンは現在の項目内を見ることを知らないからです。

比較演算子

ライブラリ間で普遍的: ==!=<><=>=

右側はリテラルです: 数値(@.age > 18)、単一引用符の文字列(@.role == 'admin')、二重引用符の文字列、truefalse、またはnull

普遍的でないもの: 2つのフィールドを互いに比較する(@.price > @.cost)、正規表現マッチ(@.email =~ /.*@example\.com/)、length()match()のような関数呼び出し。一部のライブラリはサポートし、多くはサポートしません。ToolBox HubsのJSONPathテスターはリテラル値に対する基本比較をサポートしており、実際のクエリの大多数をカバーします。

ブール組み合わせ

標準実装は条件を組み合わせる&&||をサポートします:

$.products[?(@.in_stock == true && @.price < 50)]
$.events[?(@.severity == 'error' || @.severity == 'critical')]

JSONPathで複雑なブール論理を書いている自分に気づいたら、それは通常、実際のコードに移るシグナルです — 6か月後に式を読む将来の自分が感謝します。JSONPathは単純な選択に輝きます。複雑なビジネスロジックは実際の言語に属します。

スライス: いくつかの項目だけが必要なとき

[start:end:step]はPythonスライスとまったく同じように動作します。

  • [0:5] — 最初の5項目
  • [5:] — インデックス5以降
  • [:3] — 最初の3項目([0:3]と同じ)
  • [-3:] — 最後の3項目
  • [::2] — 1つおきの項目
  • [::-1] — 逆順(どこでもサポートされていない)

スライスはJSONPathの中でもよりクリーンな部分の1つです。Pythonからの直接ポートで、予測可能な動作をします。「最初のN個の結果を与えて」や「最初の項目以外をすべて与えて」のパターンによく使います。

仕事で実際に登場するパターン

理論はいいです。実際のクエリを見てみましょう。

APIレスポンスのフィルタリング

APIがページ分割された結果を返し、特定の項目を見つけたい。テストフレームワークまたはPostmanのJSONPath:

$.data[?(@.status == 'active')].id

すべてのアクティブな項目のIDを返します。APIに「ステータスでフィルター」パラメータがない場合、これはコードで変換するより速いです。

Webhookペイロードからの値の抽出

Stripe、GitHubなどからのwebhookを処理しており、特定のフィールドを取得する必要があります。AWS EventBridgeルール、Step Functions、またはLogic AppsのJSONPath:

$.detail.payload.items[*].sku

注文内のすべての項目のSKUを返します。クラウドワークフローツールはJSONPathに依存しています。なぜなら宣言的で検査可能だからです。埋め込まれたJavaScriptはセキュリティと保守性の負担になります。

深くネストされたデータでの項目の検索

正確な構造はわかりませんが、どこかにユーザーIDがあることがわかっています:

$..userId

ネストの深さに関係なく、ドキュメント内のすべてのuserIdフィールドを返します。馴染みのないAPIレスポンスやサードパーティ統合で作業するときの探索に便利です。

スキーマライクな制約の検証

リスト内のすべての項目が特定のフィールドを持つことを確認する必要があります:

$.users[?(!@.email)]

メールがないユーザーを返します。結果が空なら、データはクリーンです。このパターンは、JSON出力をパースしてその構造をアサートするCIテストスクリプトでうまく機能します。

落とし穴 (個人リスト)

これらは私に何時間もかかったものです。

フィルターの@は必須です。 [?(@.price < 10)]の代わりに[?(price < 10)]と書くのが最も一般的なミスです。@なしでは、エンジンはpriceが現在の項目のフィールドを参照することを知りません。

フィルターは一致する項目を返し、フィルターしたフィールドではありません。 $..book[?(@.price < 10)]はbook オブジェクトを返し、価格ではありません。価格だけを取得するには: $..book[?(@.price < 10)].price

式内では引用符が重要です。 周囲の言語と混同しないように、JSONPath文字列内で単一引用符を使用してください。JSON設定ファイルではJSONPathは文字列値なので、JSONPath自体は単一引用符を使用します: "$.users[?(@.role == 'admin')]"。混同するとパースエラーが発生します。

再帰下降はシャドウマッチを見つけます。 $..nameはすべてのnameフィールドに一致し、無関係なネストされたオブジェクトのものも含みます。同じドキュメントにユーザーのnameフィールドと製品のnameフィールドがある場合、両方を返します。重要な場合は具体的にしてください。

インデックス0対プロパティ'0'。 $.items[0]は配列で動作します。$.items.0は動作する場合としない場合があります — ほとんどのパーサーは配列ではこれを拒否します(ブラケットのみ)が、オブジェクトのプロパティ名としては受け入れます。配列アクセスにはブラケットを使用してください。

空の結果はエラーではありません。 JSONPathが何にも一致しない場合、空の配列[]が得られ、例外ではありません。これは正しい動作ですが、タイポを隠す可能性があります。結果を期待していたが何も得られなかった場合は、パスを再確認してください。

RFC 9535対Goessner時代のライブラリ

JSONPathを定義した2007年の元記事は非公式でした — 例で構文を説明しましたが、エッジケースの動作を正式に指定しませんでした。異なるライブラリ実装は異なる選択をし、年月とともに違いが蓄積されました。

2024年、RFC 9535が公式仕様として公開されました。特に以下の周辺で構文と意味論を標準化します:

  • フィルター式の文法
  • 関数拡張(lengthcountmatchsearchvalue)
  • 出力の正規化されたパス(各結果はその場所を含む)
  • 正規表現マッチのI-Regexpプロファイル

新しいプロジェクトを始める場合、RFC 9535を対象とするライブラリを優先してください — Node用のjsonpath-rfc9535、Pythonポートjsonpath-rfc9535jp CLIツール。既存のコードを保守している場合、おそらくGoessner時代の実装にいるでしょう。それは大丈夫ですが、違いが存在することを知っておいてください。

ToolBox HubsのJSONPathテスターは、実装間で一貫して動作する最も一般的な演算子を実装しています。意図的にフィルター構文に保守的で、ターゲット環境で動作しないものをテストすることを避けています。

JSONPathがjqに負ける場所

jqについて言及しないとあなたを誤解させることになります。

JSONPathはJSONで値を見つけるのが得意です。jqはJSONを見つけるAND変換するのが得意です。次のことが必要なら:

  • オブジェクトを異なる形状に投影する(.users | map({id, email}))
  • 値を集約する(map(.price) | add)
  • 複数の操作を構成する
  • 複雑な条件論理を扱う

jqは劇的に優れています。JSONPathには集約、map/reduce、関数構成がありません。これらはバグではなく、スコープの決定です。JSONPathはクエリ言語、jqは変換言語です。

正しいツールは環境に依存します。JSONPathは埋め込みが簡単(依存関係なし、ただの文字列パーサー)なのでどこにでもあります。jqはバイナリを必要とし、ブラウザコンテキストや制約のある環境では使いにくいです。Postmanテストやステップ関数の入力マッピングでは、JSONPathしかありません。シェルパイプラインやサーバーサイドのデータ変換では、通常jqが優れています。

実用的なワークフロー

これが私が実際にJSONPathを使う方法です:

  1. APIレスポンスまたはJSONドキュメントをJSONフォーマッターで開いて読みやすくします。

  2. 抽出したい値を識別します。通常、メンタルにパスをトレースできます: 「users配列、項目N、roleフィールド、admin等しい。」

  3. JSONPathテスターを開き、JSONを貼り付け、式を書きます。望むものを正確に返すまで反復します。

  4. 動作する式を必要な場所にコピーします — Postmanテスト、AWS Step Function、Kubernetesセレクター。

  5. より複雑なものを構築している場合(変換、集約)、jqに切り替えます。

このワークフローは、統合から「なぜJSONPathが一致しないのか」のデバッグの何時間もを削ります。テスターは、ほとんどのチュートリアルがスキップする欠けているステップです — 構文を示し、最初の試みで正しく書けると仮定します。通常はできません、特にフィルターでは。

広いJSONワークフローのためのツール推奨

JSONPathはJSONワークフローの1つのツールです。関連ユーティリティとペアにすることで、パイプライン全体がスムーズになります:

  • JSONフォーマッター — クエリ前にきれいに表示。縮小されたJSONは読めません
  • JSON Diff — JSONPathが2つのレスポンス間で異なる結果を返したとき、何が変わったかを見るためにdiffを取る
  • JSONからTypeScript — サンプルからTypeScript型を生成し、その型を使ってスキーマに一致するJSONPathを書く
  • JSONスキーマジェネレーター — 検証用のJSONスキーマを生成。クエリ用のJSONPathを補完

JSONPathテスターは無料、ブラウザのみで、JSONをどこにも送信しません。貼り付け、クエリ、反復、コピー。それがループです。

結びの注記

JSONPathは華麗ではありません。誰もが学ぶことに興奮する言語ではありません。しかし流暢になるために1時間費やすことは、API デバッグ、クラウドワークフロー設定、データ探索の年月にわたって報われます。構文は一般的なパターンを記憶するのに十分小さいです。落とし穴は内面化するのに十分予測可能です。

新しい場合: 基本パターン($.field$..field$.array[*][?(@.field == 'value')])から始め、シンプルなものをしばらく使うまでフィルターの複雑さを避けてください。実世界のクエリのほとんどはシンプルです。複雑さは通常コードでより良く解決されるエッジケースから来ます。

よくある質問

D

著者について

Daniel Park

Senior frontend engineer based in Seoul. Seven years of experience building web applications at Korean SaaS companies, with a focus on developer tooling, web performance, and privacy-first architecture. Open-source contributor to the JavaScript ecosystem and founder of ToolPal.

詳細はこちら

この記事を共有

XLinkedIn

関連記事