json形式のAPIをcurlで確認するTips

本記事は[KIT AppDeveloper Advent Calendar 2015](http://qiita.com/advent-calendar/2015/kitappdeveloper)の20日目の記事です。

> 動作環境としてOS Xを想定しています。
> Windowsなど別の環境をサポートして書いている部分もありますが、必要な部分を適宜読み替えてください。


# curlの実行結果ってそのままじゃ見辛いですよね？

例えば、[livedoor天気情報](http://weather.livedoor.com/weather_hacks/webservice)のAPIを叩いてみます。

```
$ curl "http://weather.livedoor.com/forecast/webservice/json/v1?city=170010"
{"pinpointLocations":[{"link":"http://weather.livedoor.com/area/forecast/1720100","name":"\u91d1\u6ca2\u5e02"},{"link":"http://weather.livedoor.com/area/forecast/1720300","name":"\u5c0f\u677e\u5e02"},{"link":"http://weather.livedoor.com/area/forecast/1720600","name":"\u52a0\u8cc0\u5e02"},{"link":"http://weather.livedoor.com/area/forecast/1720900","name":"\u304b\u307b\u304f\u5e02"},{"link":"http://weather.livedoor.com/area/forecast/1721000","name":"\u767d\u5c71\u5e02"},{"link":"http://weather.livedoor.com/area/forecast/1721100","name":"\u80fd\u7f8e\u5e02"},{"link":"http://weather.livedoor.com/area/forecast/1721200","name":"\u91ce\u3005\u5e02\u5e02"},{"link":"http://weather.livedoor.com/area/forecast/1732400","name":"\u5ddd\u5317\u753a"},{"link":"http://weather.livedoor.com/area/forecast/1736100","name":"\u6d25\u5e61\u753a"},{"link":"http://weather.livedoor.com/area/forecast/1736500","name":"\u5185\u7058\u753a"}],"link":"http://weather.livedoor.com/area/forecast/170010","forecasts":[{"dateLabel":"\u4eca\u65e5","telop":"\u66c7\u308a","date":"2015-12-20","temperature":{"min":null,"max":null},"image":{"width":50,"url":"http://weather.livedoor.com/img/icon/8.gif","title":"\u66c7\u308a","height":31}},{"dateLabel":"\u660e\u65e5","telop":"\u96e8\u6642\u3005\u66c7","date":"2015-12-21","temperature":{"min":{"celsius":"6","fahrenheit":"42.8"},"max":{"celsius":"13","fahrenheit":"55.4"}},"image":{"width":50,"url":"http://weather.livedoor.com/img/icon/17.gif","title":"\u96e8\u6642\u3005\u66c7","height":31}},{"dateLabel":"\u660e\u5f8c\u65e5","telop":"\u66c7\u306e\u3061\u6674","date":"2015-12-22","temperature":{"min":null,"max":null},"image":{"width":50,"url":"http://weather.livedoor.com/img/icon/12.gif","title":"\u66c7\u306e\u3061\u6674","height":31}}],"location":{"city":"\u91d1\u6ca2","area":"\u4fe1\u8d8a\u30fb\u5317\u9678","prefecture":"\u77f3\u5ddd\u770c"},"publicTime":"2015-12-20T17:00:00\u002b0900","copyright":{"provider":[{"link":"http://tenki.jp/","name":"\u65e5\u672c\u6c17\u8c61\u5354\u4f1a"}],"link":"http://weather.livedoor.com/","title":"(C) LINE Corporation","image":{"width":118,"link":"http://weather.livedoor.com/","url":"http://weather.livedoor.com/img/cmn/livedoor.gif","title":"livedoor \u5929\u6c17\u60c5\u5831","height":26}},"title":"\u77f3\u5ddd\u770c \u91d1\u6ca2 \u306e\u5929\u6c17","description":{"text":"(\u6c17\u5727\u914d\u7f6e\u306a\u3069)\n \u672c\u5dde\u4ed8\u8fd1\u306f\u9ad8\u6c17\u5727\u306b\u8986\u308f\u308c\u3066\u3044\u307e\u3059\u3002\n\n(\u5929\u6c17\u5206\u5e03\u306a\u3069)\n \u77f3\u5ddd\u770c\u306f\u3001\u6982\u306d\u66c7\u308a\u3068\u306a\u3063\u3066\u3044\u307e\u3059\u3002\n\n(\u4eca\u591c\u306e\u5929\u6c17 20\u65e5)\n \u9ad8\u6c17\u5727\u306f\u65e5\u672c\u306e\u6771\u306b\u79fb\u52d5\u3057\u3001\u6e7f\u3063\u305f\u7a7a\u6c17\u306e\u5f71\u97ff\u3092\u53d7\u3051\u308b\u898b\u8fbc\u307f\u3067\u3059\u3002\n \u3053\u306e\u305f\u3081\u3001\n \u77f3\u5ddd\u770c\u306f\u3001\u66c7\u308a\u3067\u3057\u3087\u3046\u3002\n\n(\u660e\u65e5\u306e\u5929\u6c17 21\u65e5)\n \u6e7f\u3063\u305f\u7a7a\u6c17\u3084\u4e0a\u7a7a\u306b\u5bd2\u6c17\u3092\u4f34\u3063\u305f\u6c17\u5727\u306e\u8c37\u304c\u901a\u904e\u3059\u308b\u305f\u3081\u3001\u5927\u6c17\u306e\u72b6\u614b\u304c\n\u4e0d\u5b89\u5b9a\u3068\u306a\u308b\u898b\u8fbc\u307f\u3067\u3059\u3002\n \u3053\u306e\u305f\u3081\u3001\n \u77f3\u5ddd\u770c\u306f\u3001\u96e8\u6642\u3005\u66c7\u308a\u3067\u3001\u663c\u904e\u304e\u304b\u3089\u96f7\u3092\u4f34\u3046\u6240\u304c\u3042\u308b\u3067\u3057\u3087\u3046\u3002","publicTime":"2015-12-20T16:39:00\u002b0900"}}
```

はい、見辛いですね、やっぱり整形しないと見てられないですよね。
では実行結果をコピーして[json整形サービス](https://syncer.jp/json-prettyprint)などにペーストして確認しましょうか。

一応ですが、コピーする時に自力でコピーしていたりしませんよね？
Macであればこのように`pbcopy`をパイプで繋げるだけでクリップボードにコピーできます。
[軽く調べた](http://qiita.com/alpha_pz/items/71260cfad0c367800bb4)ところWindowsでは`clip`でできるようです。

```
$ curl "http://weather.livedoor.com/forecast/webservice/json/v1?city=170010" | pbcopy
```

ではコピーできたものを[json整形サービス](https://syncer.jp/json-prettyprint)で整形して表示して、やっと実行結果の内容を確認することができましたね。
でも、実行結果をコピーしてサービスに貼り付けてと毎回するのは手間ですよね。


# もっと簡単かつ見やすく確認する

Python 2.6以上をインストールしていれば`python -m json.tool`というものを使うことができます。
早速使ってみましょう。

※ 実行結果が長くなるので部分的に省略しています。

```
$ curl "http://weather.livedoor.com/forecast/webservice/json/v1?city=170010" | python -m json.tool
{
    "copyright": {
        "image": {
            "height": 26,
            "link": "http://weather.livedoor.com/",
            "title": "livedoor \u5929\u6c17\u60c5\u5831",
            "url": "http://weather.livedoor.com/img/cmn/livedoor.gif",
            "width": 118
        },
        "link": "http://weather.livedoor.com/",
        "provider": [
            {
                "link": "http://tenki.jp/",
                "name": "\u65e5\u672c\u6c17\u8c61\u5354\u4f1a"
            }
        ],
        "title": "(C) LINE Corporation"
    },
    "description": {
        "publicTime": "2015-12-20T16:39:00+0900",
        "text": "(\u6c17\u5727\u914d\u7f6e\u306a\u3069)\n \u672c\u5dde\u4ed8\u8fd1\u306f\u9ad8\u6c17\u5727\u306b\u8986\u308f\u308c\u3066\u3044\u307e\u3059\u3002\n\n(\u5929\u6c17\u5206\u5e03\u306a\u3069)\n \u77f3\u5ddd\u770c\u306f\u3001\u6982\u306d\u66c7\u308a\u3068\u306a\u3063\u3066\u3044\u307e\u3059\u3002\n\n(\u4eca\u591c\u306e\u5929\u6c17 20\u65e5)\n \u9ad8\u6c17\u5727\u306f\u65e5\u672c\u306e\u6771\u306b\u79fb\u52d5\u3057\u3001\u6e7f\u3063\u305f\u7a7a\u6c17\u306e\u5f71\u97ff\u3092\u53d7\u3051\u308b\u898b\u8fbc\u307f\u3067\u3059\u3002\n \u3053\u306e\u305f\u3081\u3001\n \u77f3\u5ddd\u770c\u306f\u3001\u66c7\u308a\u3067\u3057\u3087\u3046\u3002\n\n(\u660e\u65e5\u306e\u5929\u6c17 21\u65e5)\n \u6e7f\u3063\u305f\u7a7a\u6c17\u3084\u4e0a\u7a7a\u306b\u5bd2\u6c17\u3092\u4f34\u3063\u305f\u6c17\u5727\u306e\u8c37\u304c\u901a\u904e\u3059\u308b\u305f\u3081\u3001\u5927\u6c17\u306e\u72b6\u614b\u304c\n\u4e0d\u5b89\u5b9a\u3068\u306a\u308b\u898b\u8fbc\u307f\u3067\u3059\u3002\n \u3053\u306e\u305f\u3081\u3001\n \u77f3\u5ddd\u770c\u306f\u3001\u96e8\u6642\u3005\u66c7\u308a\u3067\u3001\u663c\u904e\u304e\u304b\u3089\u96f7\u3092\u4f34\u3046\u6240\u304c\u3042\u308b\u3067\u3057\u3087\u3046\u3002"
    },
    "forecasts": [ ...
    ],
    "link": "http://weather.livedoor.com/area/forecast/170010",
    "location": {
        "area": "\u4fe1\u8d8a\u30fb\u5317\u9678",
        "city": "\u91d1\u6ca2",
        "prefecture": "\u77f3\u5ddd\u770c"
    },
    "pinpointLocations": [ ...
    ],
    "publicTime": "2015-12-20T17:00:00+0900",
    "title": "\u77f3\u5ddd\u770c \u91d1\u6ca2 \u306e\u5929\u6c17"
}
```

これで整形されて見やすくなりましたね。
ただ、見やすくなったはいいですが行数が多いので出力されたものをスクロールで確認するのも見辛いですね。
そういう時にファイルを閲覧する機能を持つ`less`コマンドを利用します。

```
$ curl "http://weather.livedoor.com/forecast/webservice/json/v1?city=170010" | python -m json.tool | less 
```

実行して見るとわかると思いますが、新規ページが開かれたような感じで実行結果を確認することができると思います。

また、制限のあるAPIであれば複数回叩くのは良くないので

```
$ curl "http://weather.livedoor.com/forecast/webservice/json/v1?city=170010" | python -m json.tool > result.json
```

という風に整形したものをファイルに書き出してから`less`で確認しましょう。


# 小技

```
$ curl "http://weather.livedoor.com/forecast/webservice/json/v1?city=170010" | python -m json.tool
```

では日本語がエスケープされてしまいますね。
[同じように困っている人](http://qiita.com/t2psyto/items/123f22669c6d94d53c5f)がいて、解決策を記事にしていました。

```
$ curl "http://weather.livedoor.com/forecast/webservice/json/v1?city=170010" | python -c 'import sys,json;print json.dumps(json.loads(sys.stdin.read()),indent=4,ensure_ascii=False)'
```

このようにすれば日本語がエスケープされないので、`.bashrc`や`.zshrc`にでも

```
python -c 'import sys,json;print json.dumps(json.loads(sys.stdin.read()),indent=4,ensure_ascii=False)'
```

を定義しておけば快適なcurl生活が送れますね。