パイプでPython繋ぐの冗長過ぎ問題
以前、Pythonのjson.dumpsを使用して、curlのJSONレスポンスを見やすくする方法を書きました。
curlで日本語を含むJSONレスポンスを見やすく整形する方法
主に日本語エスケープを無効にするのが目的だったのですが、curlコマンドに直接Pythonコードを繋げて叩くため、importやindentの指定だったりと、かなり冗長になってしまうのがネックでした。
$ curl http://weather.livedoor.com/forecast/webservice/json/v1?city=130010 | python -c 'import sys,json;print json.dumps(json.loads(sys.stdin.read()),indent=4,ensure_ascii=False)'
つい最近になって、もっとシンプルに日本語エスケープやJSONの整形をしてくれるコマンドの存在を知ったのでメモしておきます。
jqコマンドを使う
以下、Macのターミナルを使用する前提で紹介。
JSONデータをパース、フィルタリングできるJSONパーサ「jq」コマンドを使用します。
jqコマンドのインストール
今回はHomebrewでjqコマンドをインストールします。
$ brew install jq
Homebrew未インストールの方は以下の記事を参照してください。
MacにHomebrewをインストールする手順とWarningの解決方法
jqコマンドの使い方
基本的な使い方としては、curlコマンドにjq
をパイプで繋げるだけです。
$ curl "http://geoapi.heartrails.com/api/json?method=searchByPostal&postal=1010047" | jq
これだけで日本語が普通に読める形で表示され、良い感じに整形もされます。
$ curl "http://geoapi.heartrails.com/api/json?method=searchByPostal&postal=1010047" | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 858 0 858 0 0 18319 0 --:--:-- --:--:-- --:--:-- 18652
{
"response": {
"location": [
{
"city": "千代田区",
"city_kana": "ちよだく",
"town": "内神田一丁目",
"town_kana": "うちかんだ1ちょうめ",
"x": "139.765943",
"y": "35.690701",
"prefecture": "東京都",
"postal": "1010047"
},
{
"city": "千代田区",
"city_kana": "ちよだく",
"town": "内神田二丁目",
"town_kana": "うちかんだ2ちょうめ",
"x": "139.768192",
"y": "35.690854",
"prefecture": "東京都",
"postal": "1010047"
},
{
"city": "千代田区",
"city_kana": "ちよだく",
"town": "内神田三丁目",
"town_kana": "うちかんだ3ちょうめ",
"x": "139.769899",
"y": "35.691568",
"prefecture": "東京都",
"postal": "1010047"
}
]
}
}
最高。
フィルタを使えばもっと便利
例えば、livedoor天気情報APIで東京都(city=130010
)の天気を取得する場合、23区や市町村の情報もズラッと入ってきます。
レスポンスから一部の情報だけを見たい場合には、jqコマンドのフィルタを使うと便利です。
JSONレスポンスのtitle
, description
, forecasts
の値だけを見たい場合は、以下のようにパイプをつないで投げます。
$ curl http://weather.livedoor.com/forecast/webservice/json/v1?city=130010 | jq '. | {title,description,forecasts}'
これでtitle
, description
, forecasts
のデータだけがフィルタリングされて出力されます。
{
"title": "東京都 東京 の天気",
"description": {
"text": " 低気圧が日本海にあって、東へ進んでいます。一方、大陸の高気圧が西日本から東日本に張り出しています。\n\n 東京地方は、おおむね晴れています。\n\n 30日は、次第に冬型の気圧配置となるため、晴れますが、気圧の谷の影響で夜は曇るでしょう。伊豆諸島では、雷を伴う所がある見込みです。\n\n 31日は、冬型の気圧配置となるため、おおむね晴れる見込みです。伊豆諸島では、雷を伴う所があるでしょう。\n\n【関東甲信地方】\n 関東甲信地方は、晴れや曇りで、雨の降っている所があります。\n\n 30日は、次第に冬型の気圧配置となるため、おおむね晴れますが、長野県や関東地方北部の山沿いでは雪や雨の降る所があるでしょう。\n\n 31日は、冬型の気圧配置となるため、おおむね晴れますが、長野県や関東地方北部の山沿いでは雪の降る所がある見込みです。\n\n 関東地方と伊豆諸島の海上では、30日から31日にかけて、うねりを伴って波が高く、しける所もあるでしょう。船舶は高波に注意してください。",
"publicTime": "2020-01-30T04:34:00+0900"
},
"forecasts": [
{
"dateLabel": "今日",
"telop": "晴のち曇",
"date": "2020-01-30",
"temperature": {
"min": null,
"max": {
"celsius": "17",
"fahrenheit": "62.6"
}
},
"image": {
"width": 50,
"url": "http://weather.livedoor.com/img/icon/5.gif",
"title": "晴のち曇",
"height": 31
}
},
{
"dateLabel": "明日",
"telop": "晴れ",
"date": "2020-01-31",
"temperature": {
"min": {
"celsius": "6",
"fahrenheit": "42.8"
},
"max": {
"celsius": "12",
"fahrenheit": "53.6"
}
},
"image": {
"width": 50,
"url": "http://weather.livedoor.com/img/icon/1.gif",
"title": "晴れ",
"height": 31
}
}
]
}
フィルタを使えばJSONから必要な情報だけをサクッと取得できますね。
階層のインデックス指定やソートなども可能な模様です。より高度にjqコマンドを使いこなしたい方は、マニュアルで詳細を見てみましょう。
jq Manual (development version)