Serialize Python dict to JSON with custom default for datetime

Convert a Python dict containing datetime and set objects into JSON by providing a custom default serializer.

Easy Python 3.9+ Aug 9, 2026 Dictionaries & sets 15 views 0 copies

Python code

21 lines
Python 3.9+
import json
from datetime import datetime

def custom_serializer(obj):
    if isinstance(obj, datetime):
        return obj.isoformat()
    if isinstance(obj, set):
        return list(obj)
    return str(obj)

data = {
    "name": "Alice",
    "created_at": datetime(2024, 3, 15, 10, 30, 45),
    "tags": {"python", "json", "serialization"},
    "score": 98.5,
    "nested": {"last_login": datetime(2024, 3, 14, 9, 0, 0)}
}

if __name__ == "__main__":
    json_output = json.dumps(data, default=custom_serializer, indent=2, sort_keys=True)
    print(json_output)

Output

stdout
{
  "created_at": "2024-03-15T10:30:45",
  "name": "Alice",
  "nested": {
    "last_login": "2024-03-14T09:00:00"
  },
  "score": 98.5,
  "tags": [
    "json",
    "python",
    "serialization"
  ]
}

How it works

The json.dumps function only serializes basic types by default. By passing default=custom_serializer, you tell it how to convert unsupported objects. The custom_serializer checks each object's type: datetimes become ISO-8601 strings, sets become lists, and any other unknown type is converted with str(). The sort_keys=True parameter orders keys alphabetically, making the output deterministic and easier to compare. The indent=2 argument adds pretty-printing for readability.

Common mistakes

  • Forgetting the `default` parameter, which causes a TypeError for datetime or set objects.
  • Not handling nested objects—the default function applies recursively, but a broken serializer breaks the whole dict.
  • Assuming set order is preserved; sets are unordered, so `list(obj)` may produce non-deterministic order.

Variations

  1. Use `json.dumps(data, default=str)` to serialize all non-serializable objects as strings, though datetime will use its default str format.
  2. Use `datetime.isoformat()` in a lambda: `default=lambda o: o.isoformat() if isinstance(o, datetime) else str(o)`.

Real-world use cases

  • Sending API responses that include timestamp fields from database records in a standardized ISO format.
  • Logging structured data that mixes standard types with datetime objects for a consistent JSON log format.
  • Storing configuration snapshots that contain both regular fields and time-based values in a JSON file.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Dictionaries & sets

Related tutorials and quizzes for this topic.