Card 05/ 08

ExampleDifficulty: Intermediate1 min

Open/Closed in the Wild: Extending Python's json Module

json.dumps cannot encode a date, and you teach it without editing a line of json.

Python's json module is closed in the strongest sense: it ships with Python, and you cannot edit it. This example shows how it was designed to be open anyway. It shares one thing with the discount rules: the closed code calls something it does not know in advance, which you supply.

Out of the box, json.dumps turns dictionaries, lists, strings and numbers into JSON text. It does not know what to do with a date.

py
import json
from datetime import date

order = {"id": 1042, "placed": date(2026, 11, 27)}
try:
    print(json.dumps(order))
except TypeError as error:
    print(f"TypeError: {error}")
OutputRan with python:3.12-slim (Python 3.12.13)
TypeError: Object of type date is not JSON serializable
json.dumps refuses a type it was not written for.

The module gives you an extension point: the default argument. When dumps meets a value it cannot encode, it calls the function you passed, and encodes whatever that function returns.

py
import json
from datetime import date


def encode_extra(value):
    if isinstance(value, date):
        return value.isoformat()
    raise TypeError(f"cannot encode {type(value).__name__}")


order = {"id": 1042, "placed": date(2026, 11, 27)}
print(json.dumps(order, default=encode_extra))
OutputRan with python:3.12-slim (Python 3.12.13)
{"id": 1042, "placed": "2026-11-27"}
A function passed as default teaches json about dates.

The date now comes out as an ISO 8601 string, and the json module did not change. Your function raises TypeError for anything else it does not recognise, which matches what json itself does, so callers see the same error as before for unsupported types.

The module offers a second extension point too: subclass json.JSONEncoder, override its default method, and pass the class as cls=. That is Meyer's original form of the principle, extension by inheritance, sitting next to Martin's form, extension by a supplied object. Both leave the library closed.