JSONPathについて

JSONPath

XML の利点としてよく強調されるのは、XML 文書を分析し、変換し、選択的にデータを抽出するための豊富なツールが利用可能であることであり、XPathはこのような強力なツールの一つ。

XPath4JSON

  • 特別なスクリプトを作成することなく、クライアント側でJSON構造体を対話的に検索し、データを抽出することができる
  • クライアントから要求されたJSONデータは、サーバー上で必要な部分だけに縮小され、サーバーレスポンスの帯域幅を最小限に抑えることができる

Wiremockで、Jsonリクエストのマッピングを記載する際にも使用する。
Wiremockについては以下の記事参照。
olafnosuke.hatenablog.com

JSONPathの書き方

オンラインのツールでJSONPathの動作検証も可能
https://jsonpath.com/

JSONPath式は、XPath式がXML文書と組み合わせて使用されるのと同じように、常にJSON構造を参照する。
JsonPathの「ルートメンバーオブジェクト」は、オブジェクトや配列に関わらず、常に$と表記される。

JSONPathはdot–notationとbracket–notationの2つの書き方がある。
dot–notation:$.store.book[0].title
bracket–notation:$['store']['book'][0]['title']

JSONPath構文要素

要素 説明
$ ルート要素。
@ 現在の要素。
.or [] 子要素
.. ディープスキャン。名前が必要な場所ならどこでも利用可能。
* ワイルドカード。名前または数値が必要な場所で利用可能。
[ (, )] 配列のインデックス
[start:end:step] 配列の分割
[?()] フィルタリングの式。式はbooleanで評価されなければならない。

関数

関数はパスの末尾で呼び出すことができる。関数への入力はパス式の出力であり、関数の出力は関数自身によって決定される。

関数 説明 出力型
min() 数値の配列の最小値を返す Double
max() 数値の配列の最大値を返す Double
avg() 数値の配列の平均値を返す Double
stddev() 数値の配列の標準偏差値を返す Double
length() 配列の長さを返す Integer
sum() 数値の配列の合計値を返す Double
keys() プロパティキー返す Set
concat(X) 新しい項目を連結したJSONPathを返す 入力と同じ
append(X) jsonパスの配列に項目を追加する 入力と同じ
first() 配列の最初の要素を返す 配列に依存
last() 配列の最後の要素を返す 配列に依存
index(X) インデックスを持つ配列の項目を返す。X が負の場合は,逆から取る。 配列に依存

フィルタで使用可能な演算子

フィルタは、配列のフィルタリングに使われる論理式である。典型的なフィルタは [?(@.age > 18)]で、@は現在処理中の項目を表す。
より複雑なフィルターは、論理演算子 &&|| を使って作ることができる。
文字列リテラルは、シングルクォートまたはダブルクォートで囲む必要があります([?(@.color == 'blue')] または [?(@.color == "blue")] )。

演算子 説明
== 左と右は等しい(ただし、1は'1'と等しくない)
!= 左と右は別物
< 左は右より小さい
<= 左は右より小さいか等しい
> 左は右より大きい
>= 左は右より大きいか等しい
=~ 左は正規表現にマッチする。[?(@.name =~ /foo.*?/i)]
in 左は右に存在する。[?(@.size in ['S', 'M'])]
nin 左は右に存在しない
subsetof 左は右の部分集合。[?(@.sizes subsetof ['S', 'M', 'L'])]
anyof 左は右と交差する。[?(@.sizes anyof ['M', 'L'])]
noneof 左と右は交差しない。[?(@.sizes noneof ['M', 'L'])]
size 左のサイズ(配列または文字列)は右のサイズと一致する
empty 左のサイズ(配列または文字列)は右のサイズと一致する

JSONPathサンプル

{ "store": {
    "book": [ 
      { "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95
      },
      { "category": "fiction",
        "author": "Evelyn Waugh",
        "title": "Sword of Honour",
        "price": 12.99
      },
      { "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": 8.99
      },
      { "category": "fiction",
        "author": "J. R. R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95
    }
  }
}
JSONPath 結果
$.store.book[*].author ストア内のすべての本の筆者
$..author 全ての筆者
$.store.* ストア内の全ての要素(本も自転車も)
$.store..price ストア内の全ての価格
$..book[2] 3冊目の本
$..book[(@.length-1)]
$..book[-1:]
最後の本
$..book[0,1]
$..book[:2]
最初の2冊の本
$..book[?(@.isbn)] isbnを持つ本
$..book[?(@.price<10)] priceが10より安い本
$..* すべての要素
$..book.length() 本の数

参考

https://github.com/json-path/JsonPath
https://goessner.net/articles/JsonPath/