第2の人生の構築ログ

自分の好きなことをやりつつ、インカムもしっかりと。実現していく過程での記録など。読書、IT系、旅行、お金に関係する話などの話題。

【Emacs】JSON の整形を Emacs の標準機能と jq でサクッと行う

f:id:dr_taka_n:20220119201353j:plain

データ交換のフォーマットとして至る所で使われる JSON ですが、データを整形して見やすくしたいことはよくあることです。

例えば、以下のような感じでデータをもらっても、パッと見よくわかりません。

[{"id":1,"name":"Leanne Graham","username":"Bret","email":"Sincere@april.biz","address":{"street":"Kulas Light","zipcode":"92998-3874"},"phone":"1-770-736-8031 x56442","company":{"name":"Romaguera-Crona"}}]

整形してあげると以下のように読みやすくなります。

[
  {
    "id": 1,
    "name": "Leanne Graham",
    "username": "Bret",
    "email": "Sincere@april.biz",
    "address": {
      "street": "Kulas Light",
      "zipcode": "92998-3874"
    },
    "phone": "1-770-736-8031 x56442",
    "company": {
      "name": "Romaguera-Crona"
    }
  }
]

このような整形を行ってくれるツールはいろいろとあります。IDE など使っていたら、IDE に整形機能が通常バンドルされているのではないでしょうか。

ここでは、Emacs を使っている場合にサクッと整形する方法を記載します。

ところで・・・最近 Emacs 使いの影が薄くなっているような気がします。。大部分の方が Vim 使いになってしまっているのでしょうか。
(いや、最近の若い子はそもそもEmacs/Viなど好き好んで使っていないのかもしれませんね。。)

jq コマンド便利です

まずは、整形はもちろん、値の列挙、フィルタリングなどもできる便利なコマンド jq です。

stedolan.github.io

Tutorialjq コマンドを使う日常のご紹介 - Qiita などのページを見ていただくと使い方、使いこなし方が把握できるのではないかと思います。

先程の整形されていないデータを jq コマンドを使って整形します。

$ echo '[{"id":1,"name":"Leanne Graham","username":"Bret","email":"Sincere@april.biz","address":{"street":"Kulas Light","zipcode":"92998-3874"},"phone":"1-770-736-8031 x56442","company":{"name":"Romaguera-Crona"}}]' | jq .
[
  {
    "id": 1,
    "name": "Leanne Graham",
    "username": "Bret",
    "email": "Sincere@april.biz",
    "address": {
      "street": "Kulas Light",
      "zipcode": "92998-3874"
    },
    "phone": "1-770-736-8031 x56442",
    "company": {
      "name": "Romaguera-Crona"
    }
  }
]

パイプ(|)を使って jq にデータを流し込んでいるだけですね。サクッと整形できました。

Emacs を使って JSON データを整形

次に、Emacs の標準パッケージを使う方法と、上記で使った外部コマンド(jq)を使うケースと2つ記載します。

標準で組み込まれている json-pretty-print-buffer/json-pretty-print を使う

Emacs 24.4 (だと思います)以降であれば、標準で JSON の整形ツールが使えます。(標準elispの中にあるjson.elで定義されています)

json-pretty-print-bufferjson-pretty-printがあり、その名の通り、buffer付きはバッファ内のものを対象として、無しの方はリージョンを対象とします。

先程使った非整形の JSON データをファイルに保存し、Emacs で開いている状態です。

f:id:dr_taka_n:20220119175623p:plain

この状態で M-x json-pretty-print-bufferしますと、

f:id:dr_taka_n:20220119175841p:plain

素晴らしいです。

Emacs から外部コマンド jq を使う

整形だけあれば、標準機能で十分ですね。外部コマンド jq を使う目的としては、jq の持っている整形以外の機能(値の列挙、フィルターなど)も使える点になります。

Emacs で表示しているデータを外部コマンドに流し込むには、M-! (shell-command-on-region) が使えます。M-!を使うことで、リージョンのデータを標準入力として指定したコマンド(ここではjq)に流し込むことができるのです。 また、M-!だけで実行するとその実行結果は別バッファに出力されますが、C-u (universal-argument) という前置引数を与えることのできるコマンドを入れることで、カレントバッファーにそのまま結果を挿入することができます。

やってみましょう。まずは、C-x h (mark-whole-buffer) でバッファの全てのデータをリージョンにしています。

f:id:dr_taka_n:20220119181152p:plain

この状態で、C-u をタイプし、続けて、M-! をタイプします。下部のコマンドバッファに"Shell command on region: "と来ますので、上述していた jq コマンドをそのまま入力します(jq .)。 f:id:dr_taka_n:20220119181808p:plain

素晴らしいです。カレントバッファがそのまま整形されました。

f:id:dr_taka_n:20220119181920p:plain

jq は普通のコマンドとして使えますので、使える機能を使っていきます。
例えば、データ内のnameの部分だけ抽出したいとします。また、結果のダブルクォーテーションは外したいとします。
これはコマンドラインでjq -r ".[].name"とやればできます。これをそのまま Emacs でも使えます。 手順は先程と同じで、”Shell command"で入力しているコマンドだけが違います。

f:id:dr_taka_n:20220119182751p:plain

ちゃんと name の値だけが抽出されました。配列の要素が1個だけですので、結果も1つです。

f:id:dr_taka_n:20220119182818p:plain

(実際のところ、このケースの場合、別のバッファに出力した方がいいでしょうね。。)

標準機能を使わずに外部コマンド jq を使うメリットはこのように、jq のフル機能が使えるところです。とても便利です。

以上です。