まくまくPythonノート
JSON 形式のテキストと Python オブジェクトの相互変換 (json.loads, json.dumps)
2021-07-24

Python 2.6 からは json モジュールが標準搭載されており、JSON 形式のテキストと、Python のオブジェクトを相互に変換することができます。

JSON 文字列 → Python オブジェクト (json.loads)

JSON 形式の文字列データから、Python オブジェクトを作成するには json.loads 関数 を使用します。

import json

data = json.loads('{"key":"value"}')
print(data['key'])  #=> 'value'

json.loads と似た関数に、json.load 関数がありますが、こちらは文字列ではなくファイルを扱います。 loads の末尾の s は、文字列を受け取ることを示しています。

Python オブジェクト → JSON 文字列 (json.dumps)

逆に、Python オブジェクトから JSON 形式のテキストを生成するには、json.dumps 関数 を使用します。

import json

obj = {'aaa':100, 'bbb':200}
json_str = json.dumps(obj)
print(json_str)

実行結果

{"bbb": 200, "aaa": 100}

整形して出力する (indent=2)

改行を入れた形で見やすく出力したい場合は、json.dumps() 関数の indent パラメータにスペース数を指定します(Python 3.2 以降は、インデントに使用する文字列そのものを指定することもできます)。

obj = {'aaa':100, 'bbb':200}
json_str = json.dumps(obj, indent=2)
print(json_str)

出力結果

{
  "bbb": 200,
  "aaa": 100
}

キーでソートして出力する (sort_keys=True)

デフォルトでは、json.dumps() は辞書オブジェクトの要素を追加順に出力します(Python 3.7 より前は不定でした)。 アルファベット順にキー名でソートして出力したい場合は、json.dumps() 関数の sort_keys パラメータを True に設定します。

print(json.dumps(obj, indent=2, sort_keys=True))

実行結果

{
  "aaa": 100,
  "bbb": 200
}

日本語を Unicode エスケープしない (ensure_ascii=False)

日本語を含んだオブジェクトを json.dumps で文字列に変換すると、デフォルトで Unicode エスケープされます。

obj = {'a': 'あいう'}
print(json.dumps(obj))  #=> {"a": "\u3042\u3044\u3046"}

これは、XSS などの脆弱性を防ぐためですが、使用用途が限られているのであれば、UTF-8 エンコーディングの日本語をそのまま出力してしまった方がわかりやすいです。 非 ASCII 文字の Unicode エンコーディングを停止するには、ensure_ascii=False オプションを指定します。

obj = {'a': 'あいう'}
print(json.dumps(obj, ensure_ascii=False))  #=> {"a": "あいう"}

(おまけ) JSON 文字列を整形する関数を作ってみる

次の pretty_json() 関数は、JSON 形式の文字列データを、きれいにインデントや改行を入れた形に整形します。 まず、json.loads で「JSON文字列→オブジェクト」の変換をしてから、json.dumps で「オブジェクト→JSONテキスト」と逆変換しています。

sample.py

import json

def pretty_json(json_text):
    """JSON文字列を読みやすく整形して返します。"""
    temp = json.loads(json_text)
    return json.dumps(temp, indent=2, sort_keys=True)

s = '{"aaa":100, "bbb":200, "ccc":300}'
print(pretty_json(s))

実行結果

{
  "aaa": 100,
  "bbb": 200,
  "ccc": 300
}

次のステップとして、パラメーターに文字列ではない通常のオブジェクトを受け取った場合でも JSON 文字列に変換できるようにしてみます。 isinstance 関数を使うと、あるオブジェクトが文字列型 (str) かどうかを判別することができます。 下記の pretty_json() 関数は、JSON 文字列、あるいは任意の Python オブジェクトを受け取って、整形された JSON 文字列として返します。

import json

def pretty_json(obj):
    temp = json.loads(obj) if isinstance(obj, str) else obj
    return json.dumps(temp, indent=2, sort_keys=True)

json_str = '{"aaa":100, "bbb":200, "ccc":300}'
json_obj = {"aaa":100, "bbb":200, "ccc":300}
print(pretty_json(json_str))  # JSON文字列も、
print(pretty_json(json_obj))  # オブジェクトもどちらも渡せる

ちなみに、python はコマンドラインで JSON テキストを整形するツール (json.tool) を提供 しているので、ローカルの JSON ファイルをササッと整形したいときにはこちらを使うと便利かもしれません。

2021-07-24