概要
JSONPathは、JSONデータから特定の値を効率的に抽出するためのクエリ言語です。Pythonでは、主にjsonpath-ngとjsonpath-rwという2つのライブラリが広く利用されています。
jsonpath-ngの特徴
- ルートノード、子ノード、ワイルドカード、配列インデックスなどの基本構文をサポート
- フィルタ内での正規表現やスクリプト式には非対応
- 複雑な論理演算は制限あり
jsonpath-rwの特徴
- 正規表現やスクリプト式を含む幅広いJSONPath構文をサポート
- 複雑な論理演算やネストされたフィルタ条件に対応
- 再帰下降演算子
..をサポート
インストール方法
各ライブラリはpipでインストール可能です。
# jsonpath-ngの場合
pip install jsonpath-ng
# jsonpath-rwの場合
pip install jsonpath-rw
基本的な使用例
以下のサンプルデータを使用して、各種抽出パターンを解説します。
from jsonpath_ng import parse
# サンプルデータの定義
shop_data = {
"shop": {
"books": [
{"genre": "novel", "name": "吾輩は猫である", "writer": "夏目漱石", "cost": 1200},
{"genre": "essay", "name": "坊っちゃん", "writer": "夏目漱石", "cost": 980},
{"genre": "novel", "name": "雪国", "writer": "川端康成", "cost": 1500}
],
"bike": {"shade": "blue", "cost": 25000}
}
}
全書籍のタイトルを取得
expr = parse('$.shop.books[*].name')
titles = [m.value for m in expr.find(shop_data)]
print(titles)
# 出力: ['吾輩は猫である', '坊っちゃん', '雪国']
全書籍の価格を取得
expr = parse('$.shop.books[*].cost')
prices = [m.value for m in expr.find(shop_data)]
print(prices)
# 出力: [1200, 980, 1500]
特定ジャンルの書籍をフィルタリング
expr = parse('$.shop.books[?(@.genre == "novel")]')
novels = [m.value for m in expr.find(shop_data)]
print(novels)
自転車の色を取得
expr = parse('$.shop.bike.shade')
bike_color = expr.find(shop_data)[0].value
print(bike_color)
# 出力: 'blue'
ネスト構造の処理
より深い階層を持つデータ構造に対するクエリ例です。
from jsonpath_ng import parse
catalog = {
"vendors": [
{
"vendor_name": "東京書店",
"products": [
{"kind": "book", "item_name": "こころ", "cost": 850},
{"kind": "dvd", "item_name": "映画セット", "cost": 3000}
]
},
{
"vendor_name": "大阪ライブラリ",
"products": [
{"kind": "book", "item_name": "人間失格", "cost": 720},
{"kind": "cd", "item_name": "クラシック集", "cost": 1800}
]
}
]
}
# 全業者名を抽出
expr = parse('$.vendors[*].vendor_name')
vendors = [m.value for m in expr.find(catalog)]
print(vendors)
# 出力: ['東京書店', '大阪ライブラリ']
高度なクエリテクニック
条件付きフィルタリング
価格が1000円以上の書籍を抽出します。
expr = parse('$.shop.books[?(@.cost >= 1000)]')
expensive_books = [m.value for m in expr.find(shop_data)]
print(expensive_books)
配列インデックスによるアクセス
# 最初の業者の最初の商品を取得
expr = parse('$.vendors[0].products[0]')
first_product = expr.find(catalog)[0].value
print(first_product)
# 出力: {'kind': 'book', 'item_name': 'こころ', 'cost': 850}
複合条件クエリ
# ジャンルが小説で、価格が1000円以上の書籍のタイトルと価格を取得
expr = parse('$.shop.books[?(@.genre == "novel" && @.cost >= 1000)]')
filtered = [m.value for m in expr.find(shop_data)]
print(filtered)
例外処理の実装
クエリ実行時のエラーを適切にハンドリングします。
from jsonpath_ng import parse
from jsonpath_ng.exceptions import JsonPathParserError
def safe_query(data, path_str):
"""安全にJSONPathクエリを実行するヘルパー関数"""
try:
expression = parse(path_str)
return [match.value for match in expression.find(data)]
except JsonPathParserError as e:
print(f"パースエラー: {e}")
return []
except Exception as e:
print(f"予期しないエラー: {e}")
return []
# 使用例
result = safe_query(shop_data, '$.shop.books[*].name')
print(result)
主なJSONPath構文一覧
| 構文 | 説明 | 例 |
|---|---|---|
$ | ルートノード | $ |
. | 子ノード | $.shop.name |
[n] | 配列インデックス | $.items[0] |
[*] | 全配列要素 | $.items[*] |
.. | 再帰的下降 | $..name |
?() | フィルタ式 | $[?(@.price > 100)] |
* | ワイルドカード | $.store.* |