Issue 30343: Subclassed json.JSONEncoder does not respect default method for supported types (original) (raw)
If you subclass json.JSONEncoder
to enable serialisation of custom types beyond those supported, you are meant to transform values of said type into a serialisable version within an overridden default
method. For example:
class MyJSONEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, MyType):
return str(o)
# Raise TypeError when we have a type we can't serialise
super().default(o)
This, however, won't work if your custom type is an instance of one of the supported types. This is because, in Lib/json/encoder.py, the _iterencode
function (defined in _make_iterencode
) type checks against supported types before it delegates to the default
method.
The reason this came up is because I wanted to serialise a named tuple into a JSON object, with keys corresponding to the named tuple's field names. Ignoring the merits (or otherwise) of this desired outcome, this can't work because a named tuple is still a tuple and thus the default
method is never called.
In Python 2.7, the _iterencode
method was part of the JSONEncoder
class, so you could override it in a subclass; even if doing so is somewhat brittle. In Python 3, this method has been moved out into the module namespace (tested in 3.6; looking through the repo, it looks like this change was made in Python 3.1), so it can't easily be monkey-patched without it affecting other things.
I believe this to be a bug. It seems reasonable to subclass at least named tuples, dictionaries and lists in such a way that you'd want a different JSON serialisation to their defaults.