💡 この記事でわかること
- JSONとは何か、Pythonの辞書やリストとどう対応するのか
json.dumps・json.loadsで、辞書とJSON文字列を相互に変換する方法json.dump・json.loadで、JSONファイルを書き込み・読み込みする方法- 日本語が「\u3042」のようになる問題の対処(
ensure_ascii=False)と、見やすく整形するindent - よくあるエラー(
JSONDecodeError・TypeError)の原因と対処法
1. JSONとは?
JSONとは、
👉 データを文字列で表現するための、決まった書き方(データ形式)です。
💡 WebAPIとのやり取りや設定ファイルの保存など、「プログラム同士でデータを受け渡す」場面で広く使われています。JavaScriptのオブジェクトに似た形をしていて、Pythonの辞書ともよく似ています。
{
"name": "太郎",
"age": 20,
"is_admin": false,
"tags": ["python", "web"]
}PythonでJSONを扱うには、標準ライブラリの json モジュールを使います。JSONのデータは、Pythonでは次のように対応します。
| JSON | Python |
|---|---|
オブジェクト { } | 辞書(dict) |
配列 [ ] | リスト(list) |
文字列 "abc" | 文字列(str) |
数値 20・1.5 | 整数(int)・小数(float) |
true / false | True / False |
null | None |
2. 辞書をJSON文字列に変換する(json.dumps)
json は標準ライブラリなので、インストールは不要で import json するだけで使えます。json.dumps() に辞書を渡すと、JSON形式の文字列が返ってきます。
import json
user = {"name": "太郎", "age": 20, "is_admin": False, "email": None, "tags": ["python", "web"]}
text = json.dumps(user)
print(text)
# {"name": "\u592a\u90ce", "age": 20, "is_admin": false, "email": null, "tags": ["python", "web"]}
print(type(text)) # <class 'str'>👉 変換後の値は「文字列」です。辞書の False が false に、None が null に変わっている点に注目してください。
👉 Pythonのモジュール(importの使い方)についての記事はこちら
ところが、日本語の「太郎」が \u592a\u90ce という見慣れない形になっています。これは、日本語などのASCII以外の文字をエスケープして出力する、json.dumps() の初期設定によるものです。ensure_ascii=False を指定すると、そのままの日本語で出力できます。また、indent を指定すると、字下げして見やすく整形できます。
print(json.dumps(user, ensure_ascii=False))
# {"name": "太郎", "age": 20, "is_admin": false, "email": null, "tags": ["python", "web"]}
print(json.dumps(user, ensure_ascii=False, indent=2))
# {
# "name": "太郎",
# "age": 20,
# "is_admin": false,
# "email": null,
# "tags": [
# "python",
# "web"
# ]
# }👉 日本語を扱うときは、ensure_ascii=False を付けるのが基本と覚えておくと安心です。indent=2 は字下げのスペースの数で、indent=4 などでも構いません。キーをアルファベット順に並べたいときは sort_keys=True も指定できます。
👉 JavaScriptのJSON(stringify・parse)についての記事はこちら
3. JSON文字列を辞書に変換する(json.loads)
逆に、JSON形式の文字列をPythonのデータに変換するのが json.loads() です。WebAPIから受け取ったデータの読み取りなどで使います。
import json
text = '{"name": "花子", "age": 25, "scores": [80, 92], "active": true, "memo": null}'
data = json.loads(text)
print(data) # {'name': '花子', 'age': 25, 'scores': [80, 92], 'active': True, 'memo': None}
print(type(data)) # <class 'dict'>
print(data["name"]) # 花子
print(data["scores"][1]) # 92👉 変換前の text はただの文字列なので text["name"] とは書けませんが、json.loads() で辞書にすると、キーを指定して値を取り出せるようになります。true が True、null が None に戻っている点も確認してください。
4. JSONファイルに書き込む(json.dump)
辞書をJSONとしてファイルに保存するときは json.dump() を使います。第1引数にデータ、第2引数に開いたファイルを渡します。
import json
user = {"name": "太郎", "age": 20, "tags": ["python", "web"]}
with open("user.json", "w", encoding="utf-8") as f:
json.dump(user, f, ensure_ascii=False, indent=2)実行すると、同じフォルダに次の内容の user.json が作られます。
{
"name": "太郎",
"age": 20,
"tags": [
"python",
"web"
]
}👉 open() の encoding="utf-8" を必ず指定してください。日本語を含むファイルが、環境によって文字化けするのを防げます。with を使ったファイルの開き方は、ファイル操作の記事で詳しく解説しています。
5. JSONファイルを読み込む(json.load)
保存したJSONファイルをPythonのデータとして読み込むのが json.load() です。
import json
with open("user.json", "r", encoding="utf-8") as f:
user = json.load(f)
print(user["name"]) # 太郎
print(user["tags"]) # ['python', 'web']6. 4つの関数の使い分け
ここまでの4つの関数は、名前がよく似ています。末尾に「s」が付くと文字列(string)、付かないとファイル、と覚えると混乱しません。
| 関数 | 扱う対象 | 変換の向き |
|---|---|---|
json.dumps(データ) | 文字列 | Python → JSON文字列 |
json.loads(文字列) | 文字列 | JSON文字列 → Python |
json.dump(データ, ファイル) | ファイル | Python → JSONファイルに書き込み |
json.load(ファイル) | ファイル | JSONファイル → Pythonに読み込み |
7. よくあるエラーと注意点
① JSONの形式が正しくないと JSONDecodeError になる
json.loads() に渡す文字列は、JSONの書き方に厳密に従う必要があります。特に間違えやすいのは次の点です。
- 文字列はダブルクォート
"で囲む(シングルクォート'は使えない) - 最後の要素のあとにカンマ
,を付けない - 空の文字列を渡さない(ファイルが空のときなどに起きやすい)
import json
json.loads("{'name': 'x'}")
# json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)👉 Pythonの辞書を print() や str() で文字列にしたものは、シングルクォートや True / None が混ざっていて、JSONではありません。辞書をJSONにしたいときは、必ず json.dumps() を使います。
読み込む内容が正しいか分からない場合は、例外処理で受け止めると、プログラムが止まるのを防げます。
import json
text = '{"name": "x",}' # 末尾にカンマがあり、JSONとして不正
try:
data = json.loads(text)
except json.JSONDecodeError:
print("JSONの形式が正しくありません")② JSONにすると、辞書のキーは文字列になる
import json
data = {1: "a", 2: "b"}
text = json.dumps(data)
print(text) # {"1": "a", "2": "b"}(キーの数字が文字列になっている)
print(json.loads(text)) # {'1': 'a', '2': 'b'}(元の数字のキーには戻らない)👉 JSONのキーは必ず文字列と決まっているためです。数字のキーで管理していたデータは、読み込んだあとに int() で戻すなどの対応が必要です。
③ JSONに変換できない型がある
import json
import datetime
data = {"at": datetime.datetime(2026, 9, 20, 10, 0)}
json.dumps(data)
# TypeError: Object of type datetime is not JSON serializabledatetime や set などは、そのままではJSONに変換できません。default=str を指定すると、変換できない値を文字列にして出力できます。
print(json.dumps(data, default=str)) # {"at": "2026-09-20 10:00:00"}👉 なお、タプル (1, 2, 3) は配列(リスト)として出力され、読み込むとリストになります。
8. 実践例:ToDoをJSONファイルに保存する
学んだことを組み合わせて、ToDoのデータをJSONファイルに保存・読み込みする例です。最初はファイルがまだないので、FileNotFoundError のときは空のリストを返すようにしています。
import json
FILE = "todo.json"
def load_todos():
try:
with open(FILE, "r", encoding="utf-8") as f:
return json.load(f)
except FileNotFoundError:
return [] # 初回はファイルがないので、空のリストから始める
def save_todos(todos):
with open(FILE, "w", encoding="utf-8") as f:
json.dump(todos, f, ensure_ascii=False, indent=2)
todos = load_todos()
todos.append({"title": "記事を書く", "done": False})
save_todos(todos)
print(load_todos()) # [{'title': '記事を書く', 'done': False}]👉 プログラムを終了してもデータが残るので、もう一度実行すると、前回のToDoに追加される形になります。設定の保存や簡単なデータの管理は、この形で書けます。
9. json関連の書き方 早見表
| 書き方 | できること |
|---|---|
json.dumps(data) | Pythonのデータ → JSON文字列 |
json.loads(text) | JSON文字列 → Pythonのデータ |
json.dump(data, f) | Pythonのデータ → JSONファイル |
json.load(f) | JSONファイル → Pythonのデータ |
ensure_ascii=False | 日本語をエスケープせず、そのまま出力する |
indent=2 | 字下げして見やすく整形する |
sort_keys=True | キーを並べ替えて出力する |
default=str | JSONにできない値を文字列にして出力する |
10. まとめ
- JSONはデータを文字列で表す形式で、Pythonでは標準ライブラリの
jsonで扱える - 辞書とJSON文字列の変換は
dumps/loads、ファイルへの読み書きはdump/load(末尾のsは文字列) - 日本語を出力するときは
ensure_ascii=False、ファイルにはencoding="utf-8"を指定する - JSONの書き方(ダブルクォート・末尾カンマなし)を間違えると
JSONDecodeErrorになる - キーは文字列になり、
datetimeなどはそのままではJSONにできない
👉 JSONの読み書きは、WebAPIとの連携やデータの保存など、さまざまな場面の土台になります。まずは辞書とファイルの組み合わせで、保存と読み込みを試してみてください。