Python | ファイル・OS 操作:JSON の ensure_ascii

Python Python
スポンサーリンク

概要(ensure_ascii は「ASCIIだけにするか、日本語をそのまま出すか」を決めるスイッチ)

json.dumps/json.dump の ensure_ascii は、非ASCII文字(日本語や絵文字など)を「Unicodeエスケープに変換するか(True)」「そのまま出力するか(False)」を制御します。初心者がまず覚えるべきは「日本語を見やすく保存したいなら ensure_ascii=False」「ファイルの文字コードは UTF-8」「newline=” で改行の事故を防ぐ」の3点です。これだけで“文字化け”や「\uXXXXだらけ」の読みにくいJSONから卒業できます。


基本の使い方(ここが重要)

文字列へ出力(dumps)で比較する

import json

data = {"msg": "こんにちは", "emoji": "😊"}

print(json.dumps(data))                       # デフォルト: ensure_ascii=True
# → {"msg": "\u3053\u3093\u306b\u3061\u306f", "emoji": "\ud83d\ude0a"}

print(json.dumps(data, ensure_ascii=False))   # 日本語・絵文字をそのまま
# → {"msg": "こんにちは", "emoji": "😊"}
Python

True は「ASCIIのみ」を保証するため、非ASCIIを必ず \uXXXX へ逃がします。False はそのまま UTF-8 で出力され、目視・手編集が圧倒的に楽になります。

ファイルへ保存(dump)は UTF-8 と newline=” をセット

import json
from pathlib import Path

path = Path("data.json")
with path.open("w", encoding="utf-8", newline="") as f:
    json.dump({"name": "太郎", "city": "東京"}, f, ensure_ascii=False)
Python

UTF-8 と ensure_ascii=False の組み合わせが定番です。これで多言語を可読で保存でき、他ツールでも扱いやすくなります。


重要ポイントの深掘り(長所・短所・往復変換・絵文字・BOM)

ensure_ascii=False の長所と、True を選ぶ理由がある場面

  • 長所(False):人が読める・差分が見やすい・ログや設定を手で編集しやすい。
  • True を選ぶ場面:古いツールや環境が「ASCIIしか通さない」制約がある場合、または意図的に非ASCIIを避けたいとき。現代のWeb/APIでは False+UTF-8 がほぼ標準的です。

読み込み(loads/dict化)はどちらでも同じになる

import json

s1 = json.dumps({"x": "あ"})                     # \uXXXX
s2 = json.dumps({"x": "あ"}, ensure_ascii=False) # あ

print(json.loads(s1)["x"])  # あ
print(json.loads(s2)["x"])  # あ
Python

読み込み側は \uXXXX を正しくデコードします。保存表現の違いは「人間にとっての見やすさ」の問題が主で、機械的にはどちらも等価です。

絵文字・多言語も UTF-8+False でそのまま

import json
data = {"jp": "ありがとう", "cn": "谢谢", "emoji": "🚀"}
print(json.dumps(data, ensure_ascii=False))
Python

絵文字や非ラテン文字も鮮明に出力されます。ログや設定ファイルに絵文字を含めたいときでも、False を選ぶだけで解決します。

Excelや一部ツール向けに BOM 付きを使う手(utf-8-sig)

import json

with open("export.json", "w", encoding="utf-8-sig", newline="") as f:
    json.dump({"name": "太郎"}, f, ensure_ascii=False)
Python

一部ツールは UTF-8 のBOM(byte order mark)がある方が文字化けしにくいことがあります。互換性が欲しい場面で検討します(BOMは好みが分かれるので、必要な時だけ)。


実務での使いどころ(設定・ログ・API・CSV混在の補助)

設定ファイルを「人が編集できる」形で保存

import json
cfg = {"service": "通知", "interval": "5分", "enabled": True}
with open("config.json", "w", encoding="utf-8", newline="") as f:
    json.dump(cfg, f, ensure_ascii=False, indent=2)
Python

indent を付けると、PRレビューや比較が格段に楽になります。ensure_ascii=False で日本語がそのまま見えます。

ログ・監査のための一行JSON(Line-delimited JSON)

import json
events = [
    {"event": "開始", "user": "太郎"},
    {"event": "更新", "user": "花子"},
]
with open("events.log", "w", encoding="utf-8", newline="") as f:
    for e in events:
        f.write(json.dumps(e, ensure_ascii=False) + "\n")
Python

後で目視やgrepする時も、そのまま読めます。

API と連携(requests なら自動で UTF-8)

import json, requests

payload = {"message": "こんにちは"}
# 手動で文字列化して送る場合
resp = requests.post("https://example.com/api", data=json.dumps(payload, ensure_ascii=False),
                     headers={"Content-Type": "application/json; charset=utf-8"})
Python

多くのAPIは UTF-8 を前提にしています。ensure_ascii=False で見やすく送っても問題ありません(サーバ側がUTF-8を受け付ける前提)。


よくある落とし穴の回避(ダブルエンコード・改行・ファイル閲覧)

すでにJSON文字列のものを「さらに dumps」しない

import json
s = json.dumps({"x": "日本語"}, ensure_ascii=False)  # これはJSON文字列
# json.dumps(s) とすると、JSON文字列をさらに「文字列として」JSON化してしまう(ダブルエンコード)
Python

「辞書をJSON文字列へ」か「JSON文字列を辞書へ」のどちらをしたいのかを明確に。文字列化済みのものへさらに dumps すると事故ります。

ファイルを開く時の newline=” を忘れない

csv と同様、プラットフォーム差の改行によるトラブルを避けるために、基本は newline=” を付けます。

ビューアによっては絵文字や非ASCIIが表示できない

古い端末やエディタでは文字化けすることがあります。チーム内の標準ビューア(VS Codeなど)を決めておくと混乱が減ります。


例題で身につける(定番から一歩先まで)

例題1:日本語をそのまま保存(インデント付き)

import json
data = {"title": "レポート", "author": "佐藤", "tags": ["分析", "可視化"]}
with open("report.json", "w", encoding="utf-8", newline="") as f:
    json.dump(data, f, ensure_ascii=False, indent=2)
Python

例題2:APIレスポンスをそのまま記録(可読性重視)

import json
resp = {"status": "ok", "message": "処理完了"}
with open("response.log", "a", encoding="utf-8", newline="") as f:
    f.write(json.dumps(resp, ensure_ascii=False) + "\n")
Python

例題3:BOM付きで互換性を上げる

import json
with open("excel_friendly.json", "w", encoding="utf-8-sig", newline="") as f:
    json.dump({"項目": "値"}, f, ensure_ascii=False)
Python

例題4:負荷試験ログ(大量・一行形式)

import json
with open("load.log", "w", encoding="utf-8", newline="") as f:
    for i in range(3):
        f.write(json.dumps({"seq": i, "msg": "テスト"}, ensure_ascii=False) + "\n")
Python

まとめ

ensure_ascii は「非ASCIIを \uXXXX に逃がすか、UTF-8でそのまま出すか」を切り替えるための核となる設定です。実務では UTF-8+ensure_ascii=False+newline=” を基本にし、設定・ログ・配布用のJSONを人が読める形で扱うのが快適。読み込みはどちらでも同じ結果になるため、保存は“人間の可読性”を優先する。必要に応じて utf-8-sig(BOM付き)や indent を組み合わせ、ダブルエンコードを避ける設計にすれば、初心者でも「文字化けしない、読みやすい、壊れない」JSON運用ができます。

タイトルとURLをコピーしました