TypeError: Object of type datetime is not JSON serializable は、json.dumps が JSON に変換できない型(datetime など)の値を受け取ったときのエラーです。 JSON にあるのは文字列・数値・真偽値・null・配列・オブジェクトだけなので、日時は文字列に変える方法を自分で決める必要があります。

直し方は、json.dumps の default= に変換の関数を渡すことです。

import json, datetime as dt, decimal, uuid

def to_json(o):
    if isinstance(o, (dt.datetime, dt.date, dt.time)):
        return o.isoformat()                 # 2026-10-11T09:30:00+09:00
    if isinstance(o, decimal.Decimal):
        return str(o)                        # "1.10"(精度を保つ。数値にしたいなら float(o))
    if isinstance(o, (set, frozenset)):
        return sorted(o)                     # 配列に
    if isinstance(o, uuid.UUID):
        return str(o)
    raise TypeError(f"Object of type {type(o).__name__} is not JSON serializable")

json.dumps(data, default=to_json, ensure_ascii=False)

確認環境:Python 3.11、pandas 3.0.6、pydantic 2.13.3、Node.js 22(確認日 2026年10月11日)。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「datetime is not JSON serializableの直し方」

再現:JSON にできない型

型 エラー
datetime Object of type datetime is not JSON serializable
date Object of type date is not JSON serializable
time Object of type time is not JSON serializable
Decimal(DB の金額など) Object of type Decimal is not JSON serializable
set Object of type set is not JSON serializable
UUID Object of type UUID is not JSON serializable
bytes Object of type bytes is not JSON serializable
pandas の Timestamp Object of type Timestamp is not JSON serializable

DB から取得した行(日時は datetime、金額は Decimal)を、そのまま json.dumps すると、まとめてこのエラーになります。

落とし穴:default=str で済ませると、形が崩れる

検索するとよく見かける default=str は、エラーは消えますが、値の形が変わります。

json.dumps({"at": now, "price": Decimal("1.10"), "tags": {"a"}}, default=str)
{"at": "2026-10-11 09:30:00+09:00", "price": "1.10", "tags": "{'a'}"}
値 default=str の結果 問題
datetime "2026-10-11 09:30:00+09:00" 日付と時刻の間が空白(ISO 8601 の T ではない)
Decimal "1.10" 数値ではなく文字列になる(受け取る側が数値を期待していると困る)
set "{'a'}" Python の表示がそのまま文字列に。受け取る側で配列として使えない

set が "{'a'}" という文字列になるのは、ほぼ確実に不具合になります。何がどう変換されるかを自分で決めた default 関数を使います。

(上の to_json を使ったとき)
{"at": "2026-10-11T09:30:00+09:00", "day": "2026-10-11", "price": "1.10", "tags": ["a", "b"], "id": "12345678-1234-5678-1234-567812345678"}

日時の書き方:isoformat とタイムゾーン

datetime isoformat()
タイムゾーンあり(Asia/Tokyo) 2026-10-11T09:30:00+09:00
タイムゾーンなし(naive) 2026-10-11T09:30:00(どこの時刻か分からない)
UTC にして Z で表す 2026-10-11T00:30:00Z(.replace("+00:00", "Z"))

タイムゾーンの無い日時を JSON にすると、受け取る側の環境の時刻として解釈されます。 確認環境の Node.js(日本時間の環境)では、"2026-10-11T09:30:00" を new Date() で読むと、日本時間の 9:30(UTC の 0:30)になりました。受け取る側が UTC のサーバーなら、9 時間ずれます。API で日時を渡すなら、タイムゾーン付き(+09:00 か Z)で書きます。

読み込む側で datetime に戻す

d = json.loads(s)
type(d["at"])                                   # str(JSON から読むと文字列のまま)
dt.datetime.fromisoformat(d["at"])              # 2026-10-11 09:30:00+09:00

json.loads は、日時の文字列を自動では datetime に戻しません。 どのキーが日時かを知っている側で、fromisoformat で戻します。

Decimal は文字列か数値か

変換 結果 向いている場面
str(o) "1.10"(文字列) 金額など、精度を落としたくない。受け取る側で Decimal に戻す
float(o) 1.1(数値) 表示用。精度の誤差が許される

float にすると、0.1 + 0.2 が 0.30000000000000004 になるような小数の誤差が入ります。金額は文字列で渡し、受け取る側の言語の Decimal 型(Java の BigDecimal など)で戻すのが安全です。

pandas の DataFrame

rec = df.to_dict("records")[0]
json.dumps(rec)              # TypeError: Object of type Timestamp is not JSON serializable

df.to_json(orient="records", date_format="iso")
# [{"at":"2026-10-11T09:30:00.000","n":1}]

DataFrame は to_json を使うと、日時も ISO 形式に変換されます。 to_dict してから json.dumps すると、pandas の Timestamp 型のままなので、このエラーになりました。

ライブラリに任せる方法

方法 結果(確認環境)
pydantic の model_dump_json() {"at":"2026-10-11T09:30:00","price":"1.10"}(datetime は ISO、Decimal は文字列)
json.JSONEncoder を継承して default を書く 何度も使うときに、エンコーダーとしてまとめる
class AppEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, (dt.datetime, dt.date)):
            return o.isoformat()
        return super().default(o)               # 対応しない型は、元どおりエラーにする

json.dumps(data, cls=AppEncoder)

対応しない型を super().default(o) でエラーに戻すのがポイントです(Python 公式ドキュメントの例と同じ形。bytes を渡すと Object of type bytes is not JSON serializable になりました)。何でも文字列にすると、default=str と同じ問題が起きます。

確認の手順(チェックリスト)

順番 確認すること 方法
1 どの型か エラー文の Object of type ○○
2 どこから来た値か DB の行(datetime・Decimal)、pandas(Timestamp)
3 変換の方法 default= に関数を渡す(default=str は避ける)
4 日時 isoformat()、タイムゾーン付きで
5 Decimal 金額は str、表示だけなら float
6 読み込む側 fromisoformat・Decimal(...) で戻す

よくある質問

Q. NaN や Infinity は JSON にできますか。 A. Python の json.dumps は、float("nan") を NaN と書き出しました。NaN は JSON の仕様に無いため、Node.js の JSON.parse では "{"v":NaN}" is not valid JSON のエラーになりました。allow_nan=False にすると、書き出す時点で ValueError: Out of range float values are not JSON compliant にできます。

Q. bytes はどうしますか。 A. 画像などのバイナリは、base64.b64encode(o).decode() で文字列にしてから渡すのが一般的です。

まとめ

  • JSON に無い型(datetime・Decimal・set・UUID)を json.dumps に渡したエラー
  • default= に変換の関数を渡す。対応しない型は TypeError に戻す
  • default=str は形が崩れる(日時が空白区切り、set が "{'a'}")
  • 日時は isoformat() +タイムゾーン。タイムゾーン無しは受け取る側の時刻として解釈される
  • 金額の Decimal は文字列で渡すと精度が落ちない
  • pandas は to_json(date_format="iso")、pydantic は model_dump_json()

参考・出典

確認日はいずれも 2026年10月11日です。

  • Python ドキュメント「json — JSON encoder and decoder」:https://docs.python.org/3/library/json.html

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「datetime is not JSON serializableの直し方」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?