超久しぶりに技術系の記事です。
PythonでJSONデータの特定のデータを取り出すサンプルをいくつか紹介します。
Web APIで情報をJSONの取得した後に必須のテクニックです!!
Contents
概要
Python+JSONフォーマットのデータは非常に相性がいい。
というのも、JSONファイルの操作に必要なライブラリが標準で実装されており、「{をどうして”をどうして・・・」みたいなロジックは一切書く必要がない。
Web APIの操作を行う作業が増えている昨今、HTTP RequestとJSONの操作ができるだけでも応用の幅が広がりますね。
1 2 3 4 5 |
import requests URL=https://hoge.com r=requests.get(URL) print(r.json()) |
これだけで、APIリクエスト・JSONの取得ができるのですから、本当に便利な世の中になったものです。
私はPythonとJSONが大好きです。
さて、APIを使用して何らかの処理の自動化を行う場合、レスポンスで取得したJSON内の「特定のデータ」を元に別のAPIを叩く・・・みたいな事もよくやりますよね。
- オブジェクトAの属性を取得するAPIを叩く
- レスポンス内のJSONの中で、特定の情報を検索して取得する
- その情報を基に、オブジェクトBを操作する
みたいな感じ。
この「JSONの中で、特定の情報を検索して取得する」ってのが難しいことがある。
なぜならば、「JSON内のデータ構造が、製品によってまちまち」だからです。
なので、今回は「よくあるJSON内のデータ取り出し方法」を列挙してみます。
(ぶっちゃけ他のブロガーさんの内容をまとめてるモノもあります)
基本編
とりあえず全部出す
色々試す前に、とりあえずJSONデータを出力したいとき。
サンプルJSON:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
{ "001":{ "name": "Catalyst", "type": "Switch" }, "002":{ "name": "ASR", "type": "Router" }, "003":{ "name": "UCS", "type": "Server" } } |
コード:
1 2 3 4 |
with open('sample.json') as f: j = json.load(f) print(j) |
結果:
1 |
{'001': {'name': 'Catalyst', 'type': 'Switch'}, '002': {'name': 'ASR', 'type': 'Router'}, '003': {'name': 'UCS', 'type': 'Server'}} |
キレイに加工して出す
JSONっぽく出力したいとき。
サンプルJSON:
上と同じ
コード:
printを以下に変更。
1 |
print("{}".format(json.dumps(j,indent=4))) |
結果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
{ "001": { "name": "Catalyst", "type": "Switch" }, "002": { "name": "ASR", "type": "Router" }, "003": { "name": "UCS", "type": "Server" } } |
しっかり””に変わってるところも注目。
キーだけ取得
ここで言う”001″とか”002″。これが取得できると、後続の処理が楽になることがある。
サンプルJSON:
上と同じ
コード:
1 2 3 4 5 |
with open('sample.json') as f: j = json.load(f) for key in j: print(key) |
結果:
1 2 3 |
001 002 003 |
値を取得
サンプルJSON:
上と同じ
コード:
1 2 |
for val in j.values(): print(val) |
結果:
1 2 3 |
{'name': 'Catalyst', 'type': 'Switch'} {'name': 'ASR', 'type': 'Router'} {'name': 'UCS', 'type': 'Server'} |
辞書型で帰ってきているので、後は煮るなり焼くなり。
キーを指定して特定の値を取得
“001”の中のデータを取得してみます。個人的にはpandasに放り込んで処理したほうが後述の作業がラクになると思いますが、とりあえず。
サンプルJSON:
上と同じ
コード:
1 |
print(j["001"]) |
これだけ!
結果:
1 |
{'name': 'Catalyst', 'type': 'Switch'} |
Pythonすごい!簡単!
応用編
上に簡単な操作を紹介しましたが、実務でこんなシンプルなJSONを操作することなんて殆どないのでは、と思います。
また、特殊な構造のJSONを扱うこともあるでしょう。
入れ子の情報を取得
例えば、以下はBitcoinのticker情報です
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
{ "status": 0, "data": [ { "ask": "895448", "bid": "895349", "high": "901321", "last": "895448", "low": "883490", "symbol": "BTC", "timestamp": "2019-10-03T05:15:12.551Z", "volume": "305.7427" } ], "responsetime": "2019-10-03T05:15:13.144Z" } |
“data”の中が入れ子になっていて、複数のdataセットを入れれるようになっています(上記ではたまたま1セットですが)。
このケースで「1つめのセットの”volume”」を取得する場合、どうしたらいいでしょう?
コード:
1 |
print(j["data"][0]["volume"]) |
結果:
1 |
305.7427 |
これが分かれば、大抵のJSONファイルからデータを抽出できるはず!多次元配列っぽくなってても余裕ですね!
キーがないリストから、情報の取得
例えば、こんなJSONがあったとします。はじめのサンプルの変化系です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[ { "name": "Catalyst", "type": "Switch" }, { "name": "ASR", "type": "Router" }, { "name": "UCS", "type": "Server" } ] |
キーがなく、ただリストで情報を含めただけです。この時点で「勘弁してくれ」状態ですが、ここで”name”を基に”type”を知りたいとします。つまり
- “Catalyst”の”type”を知りたい。(つまり”Switch”が答え。)
これ、私はギブアップしてググっちゃいました。見つかった一番キレイなコードがこちら。
1 2 3 |
item = next((item for item in j if item['name'] == 'Catalyst'), None) if item: print(item['type']) |
結果:
1 |
Switch |
こういうロジックを頭の中で描ける人、尊敬します。