JSONの構造はネストが深くなるほど視認性が下がります。
Pythonではjson.dumpsのindentオプションを使うことで、スペースやタブでインデントを付けた整形表示が簡単に行えます。
本記事では、初心者の方でも段階を踏んで理解できるように、基本から実務での注意点まで丁寧に解説します。
JSON整形表示の基本(json.dumpsのindent)
PythonのjsonモジュールでJSONを整形表示
Python標準ライブラリのjson
モジュールは、辞書やリストをJSON文字列へ変換したり、逆にJSON文字列をPythonオブジェクトへ変換できます。
特にjson.dumps
は整形表示に便利で、indent
引数を指定すると読みやすい出力になります。
# Pythonのjsonモジュールを使って整形表示する基本例
import json
data = {
"user": {"id": 123, "name": "Taro"},
"items": [{"id": 1, "qty": 2}, {"id": 2, "qty": 5}],
"paid": False
}
# indent=2で整形されたJSON文字列を作る
pretty = json.dumps(data, indent=2)
# 画面に表示する
print(pretty)
{
"user": {
"id": 123,
"name": "Taro"
},
"items": [
{
"id": 1,
"qty": 2
},
{
"id": 2,
"qty": 5
}
],
"paid": false
}
dictをJSON文字列に整形変換する基本形
基本形は辞書やリストをjson.dumps
へ渡すだけです。
出力はPythonのstr
型になりますので、そのままprint
で表示したり、ファイルに書き込めます。
import json
order = {"id": 1001, "total": 2980, "currency": "JPY"}
json_text = json.dumps(order, indent=4) # 4スペースで整形
print(type(json_text)) # 返り値の型を確認
print(json_text)
<class 'str'>
{
"id": 1001,
"total": 2980,
"currency": "JPY"
}
json.dumpsとは
json.dumps(obj, *, indent=None, ensure_ascii=True, sort_keys=False, separators=None, ...)
は、PythonオブジェクトをJSON文字列へ変換します。
indentやensure_ascii、sort_keysなどのオプションを使うと、見た目やエンコードの挙動を細かく制御できます。
indentの役割と効果
indentは各階層で付与するインデントを指定します。
整数を渡すとその数だけスペースを使い、文字列を渡すとその文字列をインデントとして使います。
たとえばindent=2
は階層ごとに2スペース、indent="\t"
はタブで下げます。
ネストが深くなるほど、読みやすさが大きく変わります。
indent=2/4/タブの違い
一般的には2スペースか4スペースがよく使われます。
タブはファイルビューアによって見え方が変わるため、チームでの合意がなければスペースを推奨します。
import json
sample = {"a": {"b": {"c": [1, 2, 3]}}}
print("indent=2")
print(json.dumps(sample, indent=2)) # 2スペース
print("\nindent=4")
print(json.dumps(sample, indent=4)) # 4スペース
print("\nindent='\\t' (タブ)")
print(json.dumps(sample, indent="\t")) # タブ
indent=2
{
"a": {
"b": {
"c": [
1,
2,
3
]
}
}
}
indent=4
{
"a": {
"b": {
"c": [
1,
2,
3
]
}
}
}
indent='\t' (タブ)
{
"a": {
"b": {
"c": [
1,
2,
3
]
}
}
}
次の表は違いの要点です。
設定 | 見た目 | 長所 | 注意点 |
---|---|---|---|
indent=2 | 小さい字下げ | 行の折返しが減り、横幅を保ちやすい | 深いネストで若干詰まって見える場合あり |
indent=4 | 大きい字下げ | 階層がより明確で把握しやすい | ファイルサイズがやや増える |
indent=”\t” | タブ字下げ | 表示幅をビューア設定で調整可能 | ビューアによって幅が変わり見え方が不統一 |
printで整形JSONを表示
整形済みJSONは文字列なので、そのままprint
関数に渡せます。
ログ出力でも同様ですが、大量データの頻繁な整形はパフォーマンスに影響するため、後述の注意点も参照してください。
import json
config = {"debug": True, "version": "1.0.0"}
print(json.dumps(config, indent=2)) # すぐに画面表示
{
"debug": true,
"version": "1.0.0"
}
日本語やキー順を整えるオプション
ensure_ascii=Falseで日本語をそのまま出力
デフォルトではensure_ascii=True
のため、日本語はエスケープされたUnicodeとして出力されます。
ensure_ascii=False
にすると、日本語をそのまま表示できます。
import json
profile = {"name": "山田太郎", "city": "東京都"}
print("ensure_ascii=True (デフォルト)")
print(json.dumps(profile, indent=2)) # \u5c71\u7530 のように出力
print("\nensure_ascii=False")
print(json.dumps(profile, indent=2, ensure_ascii=False)) # 日本語のまま
ensure_ascii=True (デフォルト)
{
"name": "\u5c71\u7530\u592a\u90ce",
"city": "\u6771\u4eac\u90fd"
}
ensure_ascii=False
{
"name": "山田太郎",
"city": "東京都"
}
日本語を扱う場合はensure_ascii=False
を基本にし、ファイルへ保存する際はUTF-8エンコーディングを指定すると安全です。
sort_keys=Trueでキーを並べ替え
sort_keys=True
で、辞書のキーをアルファベット順に整列して出力します。
設定ファイルを比較するときや、毎回同じ順序で出力したい場合に有用です。
import json
person = {"age": 30, "name": "Taro", "id": 100}
print("sort_keys=False")
print(json.dumps(person, indent=2, sort_keys=False))
print("\nsort_keys=True")
print(json.dumps(person, indent=2, sort_keys=True))
sort_keys=False
{
"age": 30,
"name": "Taro",
"id": 100
}
sort_keys=True
{
"age": 30,
"id": 100,
"name": "Taro"
}
separatorsで余計なスペースを調整
separators
は区切り文字の直後につくスペースを制御します。
デフォルトは(",", ": ")
です。
インデントしつつ、行内のスペースだけ減らすことも可能です。
import json
data = {"a": 1, "b": [1, 2]}
print("デフォルト separators")
print(json.dumps(data, indent=2)) # ":" の後にスペースあり
print("\nseparators=(',', ':') でスペース削減")
print(json.dumps(data, indent=2, separators=(",", ":"))) # ":" の後のスペースなし
デフォルト separators
{
"a": 1,
"b": [
1,
2
]
}
separators=(',', ':') でスペース削減
{
"a":1,
"b":[
1,
2
]
}
可読性を重視するならデフォルトのまま、サイズを少しでも減らしたいならseparators=(",", ":")
が目安です。
よくある使い方と落とし穴
深いJSONを読みやすくする(indentの選び方)
ネストが深いJSONでは行あたりの情報量を抑えることが読みやすさにつながります。
一般にindent=2
は横幅を保ちやすく、indent=4
は階層が明確になります。
横長の値が多い場合は2、配列やオブジェクトが深く重なる場合は4を試すとよいです。
import json
deep = {"a": {"b": {"c": {"d": {"e": [1, {"x": "y"}, 3]}}}}}
print("indent=2")
print(json.dumps(deep, indent=2))
print("\nindent=4")
print(json.dumps(deep, indent=4))
indent=2
{
"a": {
"b": {
"c": {
"d": {
"e": [
1,
{
"x": "y"
},
3
]
}
}
}
}
}
indent=4
{
"a": {
"b": {
"c": {
"d": {
"e": [
1,
{
"x": "y"
},
3
]
}
}
}
}
}
json.dumpsとjson.dumpの違い(画面表示/ファイル保存)
json.dumps
は文字列を返す関数、json.dump
はファイルオブジェクトに直接書き込む関数です。
ファイル保存時はテキストモードとエンコーディングを忘れずに指定します。
# ファイルに保存: json.dump
import json
from pathlib import Path
data = {"title": "レポート", "ok": True}
# UTF-8で保存し、日本語を可読のままにする
out = Path("output.json")
with out.open("w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False, sort_keys=True)
# 保存内容を読み戻して確認
with out.open("r", encoding="utf-8") as f:
text = f.read()
print(text)
{
"ok": true,
"title": "レポート"
}
返り値はstrである点とエンコードの注意
json.dumpsの返り値はstr
です。
バイト列として扱いたい場合は.encode("utf-8")
で明示的にエンコードします。
ファイルに書き込むときはopen(..., encoding="utf-8")
のようにエンコーディングを指定してください。
import json
obj = {"msg": "こんにちは"}
txt = json.dumps(obj, ensure_ascii=False) # 文字列
bin_data = txt.encode("utf-8") # バイト列に変換
print(type(txt), len(txt))
print(type(bin_data), len(bin_data))
<class 'str'> 16
<class 'bytes'> 26
文字数とバイト数は一致しない場合があるため、ネットワーク送信やサイズ見積りの際はバイト列で評価しましょう。
大きなJSONのパフォーマンス注意点
pretty printは開発用(本番はコンパクトに)
整形出力は読みやすさのための余白を大量に追加します。
本番のAPIレスポンスや大規模ログでは非推奨で、サイズと速度を優先するコンパクトな出力にすべきです。
具体的にはindent=None
かつseparators=(",", ":")
のように設定します。
import json
big = {"items": [{"i": i, "v": [i, i*i, str(i)]} for i in range(1000)]}
# 本番想定: コンパクトな出力
compact = json.dumps(big, separators=(",", ":"), ensure_ascii=False)
# 開発向け: 読みやすい整形
pretty = json.dumps(big, indent=2, ensure_ascii=False)
print("compact length:", len(compact))
print("pretty length:", len(pretty))
compact length: 32218
pretty length: 92226
インデントによるサイズ増加と速度への影響
インデントは改行とスペースを大量に追加します。
ネストが深いほどサイズ増加率が高くなり、生成時間も増加します。
以下はインデント幅ごとのサイズ比較です。
import json
data = {"a": [{"b": {"c": list(range(50))}} for _ in range(50)]}
raw = json.dumps(data) # デフォルト
i2 = json.dumps(data, indent=2)
i4 = json.dumps(data, indent=4)
print("no indent:", len(raw))
print("indent=2 :", len(i2), " (+", round((len(i2)-len(raw))/len(raw)*100, 1), "%)")
print("indent=4 :", len(i4), " (+", round((len(i4)-len(raw))/len(raw)*100, 1), "%)")
no indent: 10307
indent=2 : 37415 (+ 263.0 %)
indent=4 : 64219 (+ 523.1 %)
整形は開発時のデバッグや一時的なログに限定し、配布や通信では極力コンパクトにするのが原則です。
まとめ
JSONの整形表示はjson.dumpsのindentで簡単に行え、2や4スペース、タブの使い分けで読みやすさを調整できます。
日本語はensure_ascii=False
で可読に保ち、sort_keys=True
やseparators
で順序やスペースを調整すると実務で扱いやすくなります。
なお返り値はstrで、ファイル保存時はencoding="utf-8"
と組み合わせるのが安全です。
最後に、整形はサイズと速度を犠牲にする点を忘れず、本番ではコンパクトな出力を選ぶ方針を徹底してください。