Pythonで「TypeError: Object of type datetime is not JSON serializable」を解決する方法

beginner🐍 Python2026-06-18| Python 3.8以降, Linux, macOS, Windows

Error Message

TypeError: Object of type datetime is not JSON serializable
#python#json#datetime#シリアライズ#json.dumps

問題の概要Pythonの辞書をJSON文字列に変換しようとした際、プログラムがクラッシュしてしまうのは、開発者にとってよくある経験です。標準の json.dumps() メソッドを使用しても、正常な文字列の代わりに次のようなスタックトレースが表示されます:

TypeError: Object of type datetime is not JSON serializable

このエラーは通常、APIにデータを送信したり、レコードをディスクに保存したりするタイミングで発生します。特にPostgreSQL、MySQL、MongoDBなどからデータを取得し、タイムスタンプ列が自動的にPythonの datetime オブジェクトに変換される場合に、この問題に直面することが多くなります。

エラーを引き起こすコード例```

import json from datetime import datetime

data = { "id": 1024, "event": "User Signup", "timestamp": datetime.now() # このオブジェクトがクラッシュの原因になります }

この行で TypeError が発生します

json_data = json.dumps(data)


## 発生原因Pythonに組み込まれている `json` モジュールは効率的ですが、制約があります。デフォルトでは、文字列、整数、浮動小数点、ブール値など、JSONに直接対応する基本型のみをマッピングできます。JSON自体にはネイティブな「日付(Date)」型が存在しません。仕様として日付を文字列にするべきか数値にするべきかが定義されていないため、Pythonは独自に推測して処理することを拒否し、単に処理を停止します。
## 解決方法### 方法 1:手軽な修正('default' 引数の使用)小規模なスクリプトの場合は、`json.dumps()` の `default` パラメータに関数を渡します。これにより、認識できないオブジェクトに遭遇した際にエンコーダーがどのように対処すべきかを指示できます。

import json from datetime import datetime

data = {"timestamp": datetime.now()}

シリアル化できないオブジェクトを強制的に文字列に変換します

json_data = json.dumps(data, default=str)

print(json_data)

出力: {"timestamp": "2024-06-17 14:30:05.123456"}


`default=str` は高速ですが、少し強引な手法です。ISO 8601 のような、より標準化された形式を好む場合もあるでしょう。
### 方法 2:カスタムJSONエンコーダー(本番環境に推奨)大規模なアプリケーションを構築している場合は、再利用可能なエンコーダークラスを使用するのが最善です。これにより、シリアル化のロジックを1か所にまとめ、API全体での一貫性を確保できます。

import json from datetime import datetime, date

class DateTimeEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, (datetime, date)): return obj.isoformat() return super().default(obj)

data = { "created_at": datetime.now(), "is_active": True }

cls 引数を使用してカスタムロジックを適用します

json_data = json.dumps(data, cls=DateTimeEncoder)

print(json_data)


### 方法 3:データの事前処理エンコーダーの動作を変更したくない場合もあります。その代わりに、dump 関数に渡す前に辞書を手動で変換することもできます。日付フィールドが1つか2つしかない場合は、この方法の方が安全なことが多いです。

from datetime import datetime import json

data = {"last_login": datetime.now()}

浅いコピーを作成し、特定のフィールドをフォーマットします

clean_data = {**data, "last_login": data["last_login"].strftime('%Y-%m-%d %H:%M:%S')}

json_output = json.dumps(clean_data)


### 方法 4:Pydantic の使用(モダンな Python)FastAPIやモダンなデータバリデーションを使用している場合は、すでに **Pydantic** がインストールされている可能性があります。Pydantic は、追加の設定なしで複雑なシリアル化をそのまま処理できます。

from pydantic import BaseModel from datetime import datetime

class Event(BaseModel): name: str timestamp: datetime

event = Event(name="System Update", timestamp=datetime.now())

Pydantic v2 では model_dump_json() を使用します

print(event.model_dump_json())


## 検証手順修正を適用したら、データが実際に使用可能であることを確認するために以下のチェックを行ってください:
- TypeError が発生せずにスクリプトが終了することを確認する。- 出力された日付文字列が、生のオブジェクト文字列ではなく `"2024-06-17T10:00:00"` のようになっていることを確認する。- JSONを再度読み込んで、有効なJSONであることを確認する:```
try:
    json.loads(json_data)
    print("JSONは有効であり、使用準備が整っています。")
except Exception as e:
    print(f"検証失敗: {e}")

予防策とヒント- ISO 8601 への標準化: obj.isoformat() を使用してください。これは JavaScript、React、モバイルアプリなどが即座にパースできる業界標準です。- UTC の採用: datetime.now(timezone.utc) を使用してタイムゾーンのバグを回避します。Python 3.12 以降、utcnow() は非推奨となっていることに注意してください。ネストされた日付を含む複雑なJSON構造をデバッグするとき、私はよく ToolCraft の JSON Formatter を使って構造が正しいか確認します。文字列ではなく Unix タイムスタンプを扱っている場合は、彼らの Timestamp Converter が、数値が正しい日付を指しているかチェックするのに非常に便利です。どちらのツールもブラウザ内で完全に動作するため、プライバシーの観点からも優れています。

Related Error Notes