Python
Vim

[Python] jqコマンドが使えない場合にjson整形で使えるスクリプト

はじめに

コマンドラインでjsonを整形したい時、よく使われる手段としてはjqコマンドがあげられる。
しかし、jqコマンドはOS標準で用意されているコマンドではないので、サーバによってはインストールされていない場合もある。
その場合の代替え案としてpythonの標準ライブラリであるjsonを使う案がある。

pythonの標準ライブラリjsonを使う場合
$ echo '{"name":"Sato"}' | python -m json.tool
{
    "name": "Sato"
}

しかし、非ascii(日本語等)がjson内に含まれているとその文字が \uXXXXのように出力されてしまう。

$ echo '{"name":"佐藤"}' | python -m json.tool
{
    "name": "\u4f50\u85e4"
}

日本語が\uXXXXのように出力されずに、日本語として出力してくれるjson整形用のpythonスクリプトを作成した。
(python3系ではデフォルトがutf8になったので、日本語で表示されるかと期待したけど試してみたら同じ結果だった。)

検証環境

CentOS 7.5
Python 2.7.5
Python 3.6.5

スクリプトのソースコード

Python2系の場合

format_json.py
#!/usr/bin/env python
# coding: utf-8
import sys
import codecs
import json

# 標準出力をラップして常にutf-8で出力する
sys.stdout = codecs.getwriter("utf-8")(sys.stdout)

# パイプで渡された値を受け取る
standard_output_value = sys.stdin.readline()

# 文字列がjson形式かチェック
try:
    # 文字列をjsonデコード
    json_string = json.loads(standard_output_value)
except ValueError:
    # 文字列がjson形式でないことをターミナルに出力
    sys.stdout.write("No JSON object could be decoded")
    # エラーコードを返し処理を終了
    sys.exit(1)

# jsonを整形する
# ensure_asciiをFalseにすることで非asciiに対応させる
formatted_json = json.dumps(json_string,
                            ensure_ascii=False,
                            indent=4,
                            separators=(',', ': '))
# ターミナルに整形したjsonを出力する
sys.stdout.write(formatted_json)
# 正常コードを返し処理を終了
sys.exit(0)

Python3系の場合

format_json.py
#!/usr/bin/env python3.6
# coding: utf-8
import sys
import json

# パイプで渡された値を受け取る
standard_output_value = sys.stdin.readline()

# 文字列がjson形式かチェック
try:
    # 文字列をjsonデコード
    json_string = json.loads(standard_output_value)
except ValueError:
    # 文字列がjson形式でないことをターミナルに出力
    sys.stdout.write("No JSON object could be decoded")
    # エラーコードを返し処理を終了
    sys.exit(1)

# jsonを整形する
# ensure_asciiをFalseにすることで非asciiに対応させる
formatted_json = json.dumps(json_string,
                            ensure_ascii=False,
                            indent=4,
                            separators=(',', ': '))
# ターミナルに整形したjsonを出力する
sys.stdout.write(formatted_json)
# 正常コードを返し処理を終了
sys.exit(0)

使い方

その1

python scriptに対して標準出力してあげる。

$ echo '{"name":"佐藤"}' | python format_json.py 
{
    "name": "佐藤"
}

その2

まず$HOME/binにPATHを通す。

bashの設定ファイル
PATH=$PATH:$HOME/bin
$HOME/bin
$ ls -la $HOME/bin
total 8
drwxr-xr-x 2 xxxx xxxx 4096 Nov 16 09:26 .
drwxr-xr-x 7 xxxx xxxx 4096 Nov 16 11:13 ..
lrwxrwxrwx 1 xxxx xxxx   49 Nov 16 09:26 fj -> /path/to/format_json.py

そうすると下記のような感じで使うことができる。
(PATHを通す場合はスクリプトのshebangを適切なものに変更してください。)

$ echo '{"name":"佐藤"}' | fj
{
    "name": "佐藤"
}

このスクリプトを使ってVimでもjsonを整形

Vimは外部シェルを実行できる機能をもっているので、
外部シェルでこのスクリプトを使えばjsonファイルを整形することができる。

$ vim sample.json
sample.json
{"names":["山田","佐藤","鈴木"], "class":1}

PATHを通していれば:% !fj
PATHを通していなければ:% !python format_json.py
のように外部シェルコマンドを起動すれば

sample.json
{
    "names": [
        "山田",
        "佐藤",
        "鈴木"
    ],
    "class": 1
}

と整形できる。