【Python】JSONの読み込み/書き込み方法 ~dump, load, dumps, loads~

Python で json モジュールを用いて JSON の読み込み/書き込みを行う方法について解説します。
目次
Python における JSON データの利用
Python で JSON 形式のデータを読み込み/書き込みをする場合には、json モジュールを使用します。JSON とは「JavaScript Object Notation」の略で、JavaScript のオブジェクトの書き方を元にしたデータ定義方法になっています。
JavaScript で使われることを想定して定義されたものですが、Python を含めて、幅広い言語で使用ができ、Web のREST API におけるデータのやり取りのためのデータ構造や設定ファイルの管理方法としても使用されます。
この記事では、json モジュールを使って JSON データを扱う方法を紹介します。
JSON ファイルの読み込み/書き込み
dump、load
json モジュールで JSON 形式ファイルの読み込み/書き込みを行う場合は、dump 関数及び load 関数を使用します。
import json
# データを用意
data = {
"data": [
{"id": 1, "name": "Taro"},
{"id": 2, "name": "Haruka"},
{"id": 3, "name": "Sakura"},
]
}
# JSONファイルへの書き込み
with open("test.json", "w", encoding='utf-8') as f:
json.dump(data, f)
# JSONファイルの読み込み
with open("test.json", "r", encoding='utf-8') as f:
data_r = json.load(f)
print(data_r)
print(type(data_r))【test.jsonのファイルの中身】
{"data": [{"id": 1, "name": "Taro"}, {"id": 2, "name": "Haruka"}, {"id": 3, "name": "Sakura"}]}【実行結果】
{'data': [{'id': 1, 'name': 'Taro'}, {'id': 2, 'name': 'Haruka'}, {'id': 3, 'name': 'Sakura'}]}
<class 'dict'>以降で上記例におけるポイントを説明していきます。
JSON ファイルの書き込み dump
JSON ファイルへの書き込みを行っている部分は以下の部分です。
# JSONファイルへの書き込み
with open("test.json", "w", encoding='utf-8') as f:
json.dump(data, f)JSON ファイルへ書き込みを行う場合には、open 関数で .json 拡張子のファイルを開きます。入力する辞書データ(data)とファイルオブジェクト(f)を dump 関数の引数に渡すことで JSON 形式でファイルを出力することができます。
【test.jsonのファイルの中身】
{"data": [{"id": 1, "name": "Taro"}, {"id": 2, "name": "Haruka"}, {"id": 3, "name": "Sakura"}]}test.json のファイルの中身を確認すると用意した辞書データと同じになっていることが分かります。
JSON ではダブルクォーテーション(")で文字列を囲むことが仕様となっています。そのため、Python 側でシングルクォーテーション(')の文字列で辞書を作成していたとしても(")で出力されます。
JSON ファイルの読み込み load
JSON の読み込みを行っているのは以下の部分です。
# JSONファイルの読み込み
with open("test.json", "r", encoding='utf-8') as f:
data_r = json.load(f)
print(data_r)
print(type(data_r))データを読み込む際には、load 関数を使用します。上記の例では data_r にデータを読み込んで出力しています。
【実行結果】
{'data': [{'id': 1, 'name': 'Taro'}, {'id': 2, 'name': 'Haruka'}, {'id': 3, 'name': 'Sakura'}]}
<class 'dict'>実行結果を見ると辞書形式で読み込みがされていることが分かります。
Python 辞書と JSON 形式文字列間の変換
dumps、loads
上記では、JSON 形式のファイルの読み込み/書き込みについて紹介しました。ここでは、プログラム内で Python 辞書と JSON 形式文字列を変換する例を見ていきます。
Python 辞書と JSON 形式文字列を変換する際には、dumps 関数と loads 関数を使用します。ファイルの読み込み/書き込み時との違いは「s」があるかないかの違いですので注意しましょう。
import json
# データを用意
data = {
"data": [
{"id": 1, "name": "Taro"},
{"id": 2, "name": "Haruka"},
{"id": 3, "name": "Sakura"},
]
}
# JSON形式文字列への変換
json_data = json.dumps(data)
print(json_data)
print(type(json_data), "\n")
# JSON形式文字列を辞書へ変換
data_dic = json.loads(json_data)
print(data_dic)
print(type(data_dic))【実行結果】
{"data": [{"id": 1, "name": "Taro"}, {"id": 2, "name": "Haruka"}, {"id": 3, "name": "Sakura"}]}
<class 'str'>
{'data': [{'id': 1, 'name': 'Taro'}, {'id': 2, 'name': 'Haruka'}, {'id': 3, 'name': 'Sakura'}]}
<class 'dict'>以降で上記例におけるポイントを説明していきます。
Python 辞書 → JSON 形式文字列への変換 dumps
Python 辞書を JSON 形式文字列に変換しているのは以下の部分です。
# JSON形式文字列への変換 json_data = json.dumps(data) print(json_data) print(type(json_data))
JSON 形式文字列へ変換する際には、辞書を dumps 関数の引数に渡します。type で型を確認していますが、str となっていることが分かります。
【実行結果抜粋】
{"data": [{"id": 1, "name": "Taro"}, {"id": 2, "name": "Haruka"}, {"id": 3, "name": "Sakura"}]}
<class 'str'> JSON 形式文字列 → Python辞書への変換 loads
JSON 形式文字列を Python 辞書に変換しているのは以下の部分です。
# JSON形式文字列を辞書へ変換 data_dic = json.loads(json_data) print(data_dic) print(type(data_dic))
JSON 形式文字列を Python 辞書に変換するには、loads 関数に JSON 形式の文字列を渡します。type で型を確認していますが、dict となっていることが分かります。
【実行結果抜粋】
{'data': [{'id': 1, 'name': 'Taro'}, {'id': 2, 'name': 'Haruka'}, {'id': 3, 'name': 'Sakura'}]}
<class 'dict'>よく使うオプション
日本語をそのまま出力する ensure_ascii=False
json.dump() や json.dumps() で JSON を出力する場合、デフォルトでは、ensure_ascii=True が指定されています。この場合、日本語などの ASCII 以外の文字は \uXXXX の形式にエスケープされて出力されます。
一方で、日本語をそのまま JSON に出力したい場合は、ensure_ascii=False を指定します。設定ファイルとして JSON で保存したい場合などで人が中身を確認する目的がある場合には、ensure_ascii=False の指定を推奨します。
なお、ensure_ascii は JSON の書き込みや変換時の出力形式を制御するオプションであるため、load や loads の読み込み側では特に意識する必要はありません。
以下は json.dump() の例です。なお、json.dumps() でも同様に引数指定ができます。
import json
# データを用意(日本語を含む)
data = {
"data": [
{"id": 1, "name": "太郎"},
{"id": 2, "name": "はるか"},
{"id": 3, "name": "さくら"},
]
}
# JSON ファイルへの書き込み(デフォルト: ensure_ascii=True)
with open("test_ensure_ascii_true.json", "w", encoding="utf-8") as f:
json.dump(data, f)
# JSON ファイルへの書き込み(ensure_ascii=False)
with open("test_ensure_ascii_false.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False)【出力結果】
[ensure_ascii=True(デフォルト) の場合]
{"data": [{"id": 1, "name": "\u592a\u90ce"}, {"id": 2, "name": "\u306f\u308b\u304b"}, {"id": 3, "name": "\u3055\u304f\u3089"}]}
[ensure_ascii=False の場合]
{"data": [{"id": 1, "name": "太郎"}, {"id": 2, "name": "はるか"}, {"id": 3, "name": "さくら"}]}見やすく整形して出力する indent
json.dump() や json.dumps() で JSON を出力すると、デフォルトでは、改行やインデントがないため 1 行の文字列として出力されます。そのため、データ量が多い場合や、階層が深い場合には内容の確認が大変です。
このような場合には、indent でインデント幅を数値指定すると JSON を改行とインデント付きの形式で整形して出力できます。
設定ファイルとして人が目で見て内容を確認するといった場合には、indent 指定をすると非常に読みやすくなります。また、日本語を含む場合は、上記の ensure_ascii=False と組み合わせるのが最適です。
以下は json.dump() の例です。なお、json.dumps() でも同様に引数指定ができます。
import json
# データを用意
data = {
"data": [
{"id": 1, "name": "太郎"},
{"id": 2, "name": "はるか"},
{"id": 3, "name": "さくら"},
]
}
# JSON ファイルへの書き込み (デフォルト: indent=None)
with open("test_indent_none.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False)
# JSON ファイルへの書き込み (indent=2)
with open("test_indent_2.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)【出力結果】
[指定しない場合:デフォルトの indent=None]
{"data": [{"id": 1, "name": "太郎"}, {"id": 2, "name": "はるか"}, {"id": 3, "name": "さくら"}]}
[indent=2 の場合]
{
"data": [
{
"id": 1,
"name": "太郎"
},
{
"id": 2,
"name": "はるか"
},
{
"id": 3,
"name": "さくら"
}
]
}例では、indent=2 でインデントを指定しています。これは、可読性と横幅のバランスがよく、JSON のインデント幅として一般的によく使われる設定です。
結果としては、改行とインデントにより見やすくなっていることが分かります。なお、何も指定しない場合は、デフォルトの indent=None となります。
変換できない型に対するデフォルト処理を指定する default
上記の説明で少し触れましたが、json.dump() や json.dumps() では、datetime や set、bytes などの JSON にない型を含むデータを dump するとエラーとなります。例えば、以下のような辞書を変換しようとするとエラーとなります。
data = {
"id": 1,
# datetime 型はそのままでは変換できない
"created_at": datetime.datetime.now(),
# set 型もそのままでは変換できない
"tags": {"python", "json", "example"},
# bytes 型もそのままでは変換できない
"raw_data": b"binarydata",
}【エラー例】 TypeError: Object of type datetime is not JSON serializable
このような変換できない型のデータに対しては、デフォルト処理を指定する default 引数に変換処理の関数を指定することで対応することができます。
default で文字列(str)に変換する方法
最も簡単な方法としては、str に通すことで文字列に変換してしまう方法です。以下のように default=str を指定することで文字列に変換することができます。
以下は json.dump() の例です。なお、json.dumps() でも同様に引数指定ができます。
import json
from datetime import datetime, timezone, timedelta
# データを用意
data = {
"id": 1,
# datetime 型はそのままでは変換できない
"created_at": datetime.now(timezone(timedelta(hours=9))),
# set 型もそのままでは変換できない
"tags": {"python", "json", "example"},
# bytes 型もそのままでは変換できない
"raw_data": b"binarydata",
}
# JSON ファイルへの書き込み (変換できない型を文字列に変換)
with open("test_default.json", "w", encoding="utf-8") as f:
json.dump(
data,
f,
ensure_ascii=False,
indent=2,
# default 引数で変換できない型を文字列に変換
default=str,
)【出力結果】
{
"id": 1,
"created_at": "2026-01-29 06:18:43.076851+09:00",
"tags": "{'example', 'json', 'python'}",
"raw_data": "b'binarydata'"
}default で型ごとに処理を変えて変換する方法
上記の例では、すべてを str で変換したため、決まった形式にしか変更されません。しかし、実際にはより柔軟に変換を指定したくなることがあります。例えば、以下のように変えたいとします。(例のため、もちろん他の変換方法を考えても構いません)
datetime:日本時間の ISO 形式にしたい。set:リスト形式にしたい。bytes:base64 でエンコードしてから文字列にしたい。
このような場合には、以下の default_serializer のような変換のための関数を用意して、default=default_serializer のように引数に渡します。なお、関数自体を渡すため () は付けないように注意してください。
import base64
import json
from datetime import datetime, timezone, timedelta
# from zoneinfo import ZoneInfo
def default_serializer(obj):
"""変換できない型ごとに処理を分ける例"""
if isinstance(obj, datetime):
# datetime 型は ISO 形式の文字列に変換 (タイムゾーンを日本に設定)
return obj.astimezone(timezone(timedelta(hours=9))).isoformat()
# または ZoneInfo を使う場合 (ただし、pip install tzdata が必要な場合あり)
# return obj.astimezone(ZoneInfo("Asia/Tokyo")).isoformat()
elif isinstance(obj, set):
# set 型はリストに変換
return list(obj)
elif isinstance(obj, bytes):
# bytes 型は base64 エンコードして文字列に変換
return base64.b64encode(obj).decode("utf-8")
else:
raise TypeError(f"Type {type(obj)} not serializable")
# データを用意
data = {
"id": 1,
# datetime 型はそのままでは変換できない
"created_at": datetime.now(timezone(timedelta(hours=9))),
# set 型もそのままでは変換できない
"tags": {"python", "json", "example"},
# bytes 型もそのままでは変換できない
"raw_data": b"binarydata",
}
# JSON ファイルへの書き込み (変換できない型を文字列に変換)
with open("test_default_serializer.json", "w", encoding="utf-8") as f:
json.dump(
data,
f,
ensure_ascii=False,
indent=2,
# default 引数で変換できない型ごとに処理を分ける関数を指定
default=default_serializer,
)【出力結果】
{
"id": 1,
"created_at": "2026-01-29T06:19:07.000762+09:00",
"tags": [
"python",
"json",
"example"
],
"raw_data": "YmluYXJ5ZGF0YQ=="
}例では、default_serializer が受け取った引数のオブジェクト(obj)の型を isinstance で判定して処理を分岐し、変換した文字列を返却しています。
それぞれの型に以下のような変換をして返却をしています。
| 型 | 変換方法の例 |
|---|---|
datetime | obj.astimezone(timezone(timedelta(hours=9))).isoformat()または obj.astimezone(ZoneInfo("Asia/Tokyo")).isoformat() |
set | list(obj) |
bytes | base64.b64encode(obj).decode("utf-8") |
上記は、1 例の変換です。必要な変換のための関数さえ用意すれば、上記以外にも必要な形式に柔軟に変更できます。
まとめ
Python で json モジュールを用いて JSON の読み込み/書き込みを行う方法について解説しました。
JSON とは「JavaScript Object Notation」の略で、JavaScript のオブジェクトの書き方を元にしたデータ定義方法で、Web のREST API におけるデータのやり取りのためのデータ構造や設定ファイルの管理方法としても使用されます。
この記事では、dump、load、dumps、loads といった基本的な関数の使い方を例を使って紹介しています。また、実務でよく使うオプションとして各種便利な引数について、説明しました。
JSON は、プログラム開発でよく使用するデータ形式です。ぜひ json モジュールの使い方を覚えて、うまく使いこなしてもらえたらと思います。
上記で紹介しているソースコードについては GitHub にて公開しています。参考にしていただければと思います。

