No, that’s not reasonable. e.g. the collection classes defaultdict, Counter, OrderedDict would all produce the same JSON output for the same values. (while other stdlib maplike raise TypeError)
#!/usr/bin/env python3
"""
Demo: passing various collections mapping types directly to json.dumps()
Python: 3.14
"""
import json
from collections import defaultdict, Counter, OrderedDict, ChainMap, UserDict
DEMO_ITEMS = [("a", 1), ("b", 2), ("c", 3)]
def try_dump(label: str, obj):
print(f"\n{label}")
try:
print(json.dumps(obj, indent=2, sort_keys=True))
except TypeError as e:
print(f"TypeError: {e}")
def main():
# 1. defaultdict -> dict subclass (WORKS)
dd = defaultdict(int, DEMO_ITEMS)
try_dump("defaultdict", dd)
# 2. Counter -> dict subclass (WORKS)
counter = Counter(dict(DEMO_ITEMS))
try_dump("Counter", counter)
# 3. OrderedDict -> dict subclass (WORKS)
od = OrderedDict(DEMO_ITEMS)
try_dump("OrderedDict", od)
# 4. ChainMap -> mapping view (FAILS)
cm = ChainMap(
{"a": 1, "b": 2},
{"b": 20, "c": 3},
)
try_dump("ChainMap", cm)
# 5. UserDict -> dict wrapper (FAILS)
ud = UserDict(dict(DEMO_ITEMS))
try_dump("UserDict", ud)
if __name__ == "__main__":
main()
output:
defaultdict
{
"a": 1,
"b": 2,
"c": 3
}
Counter
{
"a": 1,
"b": 2,
"c": 3
}
OrderedDict
{
"a": 1,
"b": 2,
"c": 3
}
ChainMap
TypeError: Object of type ChainMap is not JSON serializable
UserDict
TypeError: Object of type UserDict is not JSON serializable
what I think would be reasonable from an end-user viewpoint is stdlib json just to work with any than is a duck-typed Mapping.
Since I personally generally consider instance checks a poor Liskov substiution violating practice, I did some searching on Python philosphy and came across this 2015 GvR quote:
Actually, "eat your own dogfood" is not one of the goals of the stdlib -- nor is it supposed to be an example of how to code. This is often misunderstood. The stdlib contains a lot of Python code, and you can learn a lot from it, but good coding habits aren't generally something you learn there -- the code is crusty (some of the oldest Python code in existence lives in the stdlib!), often has to bend over backwards to support backward compatibility, and is riddled with performance hacks.
Based on some events in the distant past, there's actually an active ban against sweeping changes to the stdlib that attempt to "modernize" it or use new features -- because there is so much code in the stdlib, review of such sweeping (often near-mechanical) changes is inevitably less thorough than when a new feature is implemented, and even the best tests don't catch everything, so regressions in dark corners are often the result.
I’m not CPython knowledgeable enough about the stldib JSON implementation to know whether, in 2025, with the potential additon of frozendict to the json instance checks to the module, whether the trade-off between performance and what would a user expect has shifted. Which is the why this is a revisit the idea instead of pull request or pre-PEP.