###はじめに
pythonでは、JSON形式のデータをdict型(辞書型配列)に変換して扱うケースは多いと思います。その際、JSONの階層が可変であったり、list型を含んでいたりするなどの複雑な構造を持つデータに対して、特定のKeyを指定して値を検索・取得できる関数があると便利だなと考え、勉強の一環で作ってみました。
※既にあるのかも知れませんが、ググっても出てこなかったのであくまで教材・課題のつもりで...
※ご指摘、ご指南いただけるとありがたいです
###環境
macOS Monterey 12.0.1
Python 3.9.2
Visual Studio Code
###コード
関数内部で関数自身を呼び(再帰関数)、ネストが可変でも対応できるように実装。list型が含まれる場合にも対応しています。
def dict_search(d,key):
if not d or not key:
return None
elif isinstance(d, dict):
if key in d:
return d.get(key)
else:
l = [dict_search(d.get(dkey),key) for dkey in d if isinstance(d.get(dkey),dict) or isinstance(d.get(dkey),list)]
return [lv for lv in l if not lv is None].pop(0) if any(l) else None
elif isinstance(d,list):
li = [dict_search(e,key) for e in d if isinstance(e,dict) or isinstance(e,list)]
return [liv for liv in li if not liv is None].pop(0) if any(li) else None
else:
return None
###動作検証
実際にネスト深めのJSONファイル(sumple.json)を用意して検証してみます。同じ階層のディレクトリに以下のファイルがある環境とします。
・sumple.json
・util.py
・test.py
{
"data": {
"orders": {
"edges": [
{
"node": {
"id": "4595490455781",
"nodeName": "#123456",
"customer": {
"id": "abcdefg@hijklmn.com",
"name": "kajuta"
}
}
}
]
}
}
}
#####:使用例:
別ファイル(util.py)に関数を定義したので、from ~ importを使って関数をインポートして使用してみます。jsonファイルの読み込みについての説明は割愛します。
from util import dict_search
import json
# jsonを読み込んでdictに変換
with open('sumple.json','r') as f:
j_dict = json.load(f)
# keyを指定してdict内の要素を取得(この例では'name'の値を取得)
result = dict_search(j_dict,'name')
# 出力
print(result)
実行結果は以下のとおり。途中でlistを含む階層の奥にある"name"の値を取得できているのがわかります。
kajuta
#####:検証:
「name」というkeyが別階層に重複して存在するサンプルで検証
{
"node": {
"id": "4595490455781",
"name": "#123456",
"customer": {
"id": "abcdefg@hijklmn.com",
"name": "kajuta"
}
}
}
実行結果は予想通り、浅い階層から先にヒットしました。
#123456
このようにkeyが重複して存在する場合に、何番目の要素にヒットさせるかを、引数で指定できるようにしても面白いかもしれません。
###おわりに
最近、API連携などの開発を行なっていて、その際に得られたJSON形式のデータから特定の値を取得する方法をいろいろ模索していました。大抵は与えられるJSONの階層やKeyが事前にわかっている場合が多いとは思いますが、階層が複雑な場合や可変の場合のベストな方法はないかと思い、勉強のつもりで自分なりに考えてみたので投稿しました。
ご指摘・ご指南等あれば、是非ともよろしくお願いします。
###参考
・Pythonで再帰関数を作る方法【初心者向け】
・Pythonで理解する再帰関数
・Pythonのリストの深さを再帰的に計算する:空のリストの扱いに注意しよう