Python Tips: JSON を整形して表示したい

今回は JSON 形式の文字列を Python で整形して表示する方法をご紹介します。

今回は次の 2 つのパターンを取り上げてみます。

  • シンタックスハイライトなし
  • シンタックスハイライトあり

早速見ていきましょう。

シンタックスハイライトなし

シンタックスハイライトが要らない場合は、標準ライブラリの json が使えます。

JSON が文字列に格納されている場合

JSON を格納した文字列が Python コードの中で取得できている場合は、いったん loads() で読み込んだ後に dumps() で再度ダンプし直すと OK です。その際に dumps() のオプション引数 indent を指定することでインデントの大きさを決めることができます。

import json

JSON_SAMPLE = '{"_meta": {"hash": {"sha256": "hash"}, "pipfile-spec": 6, "requires": {"python_version": "3.6"}, "sources": [{"name": "pypi", "url": "https://pypi.python.org/simple", "verify_ssl": true } ] } }'

data = json.loads(JSON_SAMPLE)
print(json.dumps(data, indent=2))

出力結果:

{
  "_meta": {
    "hash": {
      "sha256": "hash"
    },
    "pipfile-spec": 6,
    "requires": {
      "python_version": "3.6"
    },
    "sources": [
      {
        "name": "pypi",
        "url": "https://pypi.python.org/simple",
        "verify_ssl": true
      }
    ]
  }
}

JSON がファイルに格納されている場合

JSON 文字列がファイルに格納されている場合は、 load()open() を使用します。

上のコードの場合は loads() の部分を load() に変えて、引数を文字列からファイルオブジェクトに変更すれば OK です。

import json

JSON_FILE = 'data.json'

with open(JSON_FILE) as f:
    data = json.load(f)
print(json.dumps(data, indent=2))

Python プログラムの中ではなくターミナル上で処理できればそれで十分な場合は、 json.tool モジュールを使う方法がお手軽でおすすめです。 json.tool は次の形で利用することができます。

$ python -m json.tool < data.json
{
  "_meta": {
    "hash": {
      "sha256": "hash"
    },
    "pipfile-spec": 6,
    "requires": {
      "python_version": "3.6"
    },
    "sources": [
      {
        "name": "pypi",
        "url": "https://pypi.python.org/simple",
        "verify_ssl": true
      }
    ]
  }
}

python -m json.tool に JSON 文字列を渡す方法には、上の「標準入力で渡す方法」の他に「ファイル名を引数として渡す方法」もあります。

$ python -m json.tool data.json

出力結果はどちらも同じです。

ちなみに、 python -m json.tool のヘルプは次のとおりになっています。

python -m json.tool -h
usage: python -m json.tool [-h] [--sort-keys] [infile] [outfile]

A simple command line interface for json module to validate and pretty-print JSON objects.

positional arguments:
  infile       a JSON file to be validated or pretty-printed
  outfile      write the output of infile to outfile

optional arguments:
  -h, --help   show this help message and exit
  --sort-keys  sort the output of dictionaries alphabetically by key

私は使ったことはありませんが、 dict 型のキーをアルファベット順(辞書順)に並べられる --sort-keys というオプションがあるようです。

続いて シンタックスハイライトありの方法を見ていきましょう。

シンタックスハイライトあり

シンタックスハイライトを施して JSON を表示する機能は(私が知るかぎり) Python の標準ライブラリには無いので、何らかの非標準のライブラリを使用するか自分で書くかのどちらかになります。おすすめなのは pygments というライブラリを使用する方法です。

シンタックスハイライトなしの場合と同様に JSON が Python コード内で文字列として取得できている場合から見ていきましょう。

JSON が文字列に格納されている場合

pygments.highlight() 関数にコードの文字列を渡すと、シンタックスハイライトを施した形で文字列を返してくれるので、それを利用します。

import json

from pygments import highlight
from pygments.lexers import JsonLexer
from pygments.formatters import TerminalFormatter

JSON_SAMPLE = '{"_meta": {"hash": {"sha256": "hash"}, "pipfile-spec": 6, "requires": {"python_version": "3.6"}, "sources": [{"name": "pypi", "url": "https://pypi.python.org/simple", "verify_ssl": true } ] } }'

data = json.loads(JSON_SAMPLE)
formatted_data = json.dumps(data, indent=2)
print(highlight(formatted_data, JsonLexer(), TerminalFormatter()))

このコードの出力は次のとおりとなります。ターミナル上ではきれいにハイライトが行われて表示されます。

{
  "_meta": {
    "hash": {
      "sha256": "hash"
    },
    "pipfile-spec": 6,
    "requires": {
      "python_version": "3.6"
    },
    "sources": [
      {
        "name": "pypi",
        "url": "https://pypi.python.org/simple",
        "verify_ssl": true
      }
    ]
  }
}

出力をブラウザで利用したい場合等は、 TerminalFormatter の代わりに HtmlFormatter を利用することが利用できます。

import json

from pygments import highlight
from pygments.lexers import JsonLexer
from pygments.formatters import TerminalFormatter

JSON_SAMPLE = '{"_meta": {"hash": {"sha256": "hash"}, "pipfile-spec": 6, "requires": {"python_version": "3.6"}, "sources": [{"name": "pypi", "url": "https://pypi.python.org/simple", "verify_ssl": true } ] } }'

data = json.loads(JSON_SAMPLE)
formatted_data = json.dumps(data, indent=2)
print(highlight(formatted_data, JsonLexer(), TerminalFormatter()))

JSON がファイルに格納されている場合

JSON がファイルに格納されている場合は、もしターミナル上で扱えればよいだけであれば、 pygments が提供するコマンドラインツール pygmentize を使う方法がシンプルでおすすめです。

改行やインデントを保ったままハイライトだけができればよいのであれば、 pygmentize コマンドをそのまま使用すれば OK です。

$ pygmentize data.json
{"_meta": {"hash": {"sha256": "hash"}, "pipfile-spec": 6, "requires": {"python_version": "3.6"}, "sources": [{"name": "pypi", "url": "https://pypi.python.org/simple", "verify_ssl": true } ] } }

ファイルの拡張子が json の場合は自動で JSON と認識してくれるようです。拡張子が json 以外の場合は -l (--lexer) オプションでフォーマットが JSON であることを伝えれば OK です。

$ pygmentize -l json Pipfile.lock

改行やインデントをよきように調整してなおかつハイライトしてほしい場合は、標準ライブラリ json と組み合わせて使うとよいかと思います。 pygmentize コマンドも、対象のファイルが指定されなければ代わりに標準入力の文字列を処理してくれます。

$ python -m json.tool json_data.json | pygmentize -l json
{
    "_meta": {
        "hash": {
            "sha256": "hash"
        },
        "pipfile-spec": 6,
        "requires": {
            "python_version": "3.6"
        },
        "sources": [
            {
                "name": "pypi",
                "url": "https://pypi.python.org/simple",
                "verify_ssl": true
            }
        ]
    }
}

ヘルプドキュメントの分量が多いのでここには掲載しませんが、 pygmentize には豊富なオプションがあるので、使ってみたい方は一度確認してから使ってみることをおすすめします。

$ pygmentize --help

参考