Skip to content

Instantly share code, notes, and snippets.

@yu81
Last active December 19, 2015 10:29
Show Gist options
  • Save yu81/5940254 to your computer and use it in GitHub Desktop.
Save yu81/5940254 to your computer and use it in GitHub Desktop.

jqを使ってJSONを処理する

jq というWritten in C な、ようやるわなJSONプロセッサがあってですね。

フィルタやちょっとした算術演算もできて、端末でAPI使った開発するのが大変捗る。
curl + jq で結構何とかなる。

インストール

簡単なので略。
ビルドも不要、つーか、ダウンロードした時点で圧縮もされてない実行可能バイナリが手に入る。
v1.3で600KBくらい。
ダウンロードして適当なところにおいてパスを通して下さいな。

実際にAPIを叩く

APIキー不要でJSON返してくれるような太っ腹なWEBサービスとかまー無いので、
公的なやつをごそごそしてたら地震関連のやつがあったのでこれを使う。
自治体別被害地震検索API | J-SHIS

こんなクエリを投げて、

curl "http://www.j-shis.bosai.go.jp/map/api/fltsearch?areacode=A08220&ecode=ALL_NT_A&mode=C&version=Y2010&case=MAX&period=P_T50&format=json&ijma=45&param=0" |
jq'.'

jqでフォーマットしたレスポンスは以下。 areacodeの仔細は調べてないけど、たぶん東京あたり。
50年内に震度5弱以上を観測するであろう地震の発生確率が返ってくる。

{
  "Fault": [
    {
      "eqgroup": "A",
      "ltecase": "1",
      "eqcategory": "1",
      "rank": "1",
      "magnitude": "-8",
      "pex": "190677",
      "ltecode": "ATOKI",
      "eqcode": "PLE_ANNKI",
      "probability": "0.97300000",
      "ltename": "想定東海地震",
      "score": "1.855e+05",
      "case": "AVR"
    },
    {
      "eqgroup": "A",
      "ltecase": "1",
      "eqcategory": "1",
      "rank": "2",
      "magnitude": "-7.9",
      "pex": "197601",
      "ltecode": "AKNTO",
      "eqcode": "PLE_AKNTO",
      "probability": "0.01380000",
      "ltename": "大正型関東地震",
      "score": "2.727e+03",
      "case": "AVR"
    },
    {
      "eqgroup": "A",
      "ltecase": "1",
      "eqcategory": "2",
      "rank": "3",
      "magnitude": "-7.0",
      "pex": "652",
      "ltecode": "AIBRK",
      "eqcode": "PSE_AIBRK",
      "probability": "1.00000000",
      "ltename": "茨城県沖の地震",
      "score": "6.522e+02",
      "case": "AVR"
    },
    {
      "eqgroup": "A",
      "ltecase": "1",
      "eqcategory": "3",
      "rank": "4",
      "magnitude": "-6.8",
      "pex": "14409",
      "ltecode": "F003401",
      "eqcode": "LND_A98F",
      "probability": "0.03660000",
      "ltename": "立川断層帯",
      "score": "5.274e+02",
      "case": "MAX"
    },
    {
      "eqgroup": "A",
      "ltecase": "1",
      "eqcategory": "3",
      "rank": "5",
      "magnitude": "-7.4",
      "pex": "198305",
      "ltecode": "F003101",
      "eqcode": "LND_A98F",
      "probability": "0.00014100",
      "ltename": "関東平野北西縁断層帯主部",
      "score": "2.796e+01",
      "case": "MAX"
    },
    {
      "eqgroup": "A",
      "ltecase": "1",
      "eqcategory": "3",
      "rank": "6",
      "magnitude": "-6.9",
      "pex": "12312",
      "ltecode": "F003001",
      "eqcode": "LND_A98F",
      "probability": "0.00000000",
      "ltename": "関谷断層",
      "score": "0.000e+00",
      "case": "MAX"
    }
  ],
  "status": "Success",
  "metaData": {
    "ijma": "45",
    "period": "P_T50",
    "lang": "ja",
    "areacode": "A08220",
    "mode": "C",
    "version": "Y2010",
    "case": "MAX",
    "ecode": "ALL_NT_A",
    "param": "0"
  }
}

同じクエリで、Fault.probability が0.8以上(確率80%以上)のやつを抽出するには、jqのクエリだけ以下の様にしてやる。

curl "http://www.j-shis.bosai.go.jp/map/api/fltsearch?areacode=A08220&ecode=ALL_NT_A&mode=C&version=Y2010&case=MAX&period=P_T50&format=json&ijma=45&param=0" |
jq '.Fault |
map(select((.probability | tonumber) > 0.8))'

以下の様なつらいレスポンスが返ってくる。

[
  {
    "eqgroup": "A",
    "ltecase": "1",
    "eqcategory": "1",
    "rank": "1",
    "magnitude": "-8",
    "pex": "190677",
    "ltecode": "ATOKI",
    "eqcode": "PLE_ANNKI",
    "probability": "0.97300000",
    "ltename": "想定東海地震",
    "score": "1.855e+05",
    "case": "AVR"
  },
  {
    "eqgroup": "A",
    "ltecase": "1",
    "eqcategory": "2",
    "rank": "3",
    "magnitude": "-7.0",
    "pex": "652",
    "ltecode": "AIBRK",
    "eqcode": "PSE_AIBRK",
    "probability": "1.00000000",
    "ltename": "茨城県沖の地震",
    "score": "6.522e+02",
    "case": "AVR"
  }
]

茨城沖ェ…

使った関数

map

  • 入力の各配列に対して引数の操作を行う。
    • 普通にmap。

select

  • 引数の操作が真なら入力をそのまま返し、偽なら何も出力しない。
  • jqもnullはあるみたいだけど出力無しとは違うのかよく分かってない。
  • map(select()) は 公式マニュアル によるとおすすめイディオムっぽい。

tonumber

  • 入力を数値型に変換する。
    • いちおうjqにも型はある。 jq Manual::Types and Values
    • object.tonumber()とかtonumber(数値文字列)じゃなくて、入力を引数にとる。
      何かのカウントの和を取るなら、map(.Count | tonumber) | add みたいな感じ。

参考

jq公式

自治体別被害地震検索API

suz-lab - blog

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment