This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Subclassed json.JSONEncoder does not respect default method for supported types
Type: behavior Stage:
Components: Library (Lib) Versions: Python 3.6
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: Xophmeister, eric.araujo
Priority: normal Keywords:

Created on 2017-05-11 13:58 by Xophmeister, last changed 2022-04-11 14:58 by admin.

Pull Requests
URL Status Linked Edit
PR 1558 closed Xophmeister, 2017-05-12 15:50
Messages (3)
msg293494 - (view) Author: Christopher Harrison (Xophmeister) Date: 2017-05-11 13:58
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.
msg293554 - (view) Author: Christopher Harrison (Xophmeister) Date: 2017-05-12 15:50
I have written a proof-of-concept implementation and submitted a pull request. See the PR for details: https://github.com/python/cpython/pull/1558

(My CLA is pending; submitted around 2017-05-12T10:30:00Z+0100)
msg379046 - (view) Author: Éric Araujo (eric.araujo) * (Python committer) Date: 2020-10-19 22:32
See also https://bugs.python.org/issue34858

This needs a discussion on python-ideas or -dev.
History
Date User Action Args
2022-04-11 14:58:46adminsetgithub: 74528
2020-10-19 22:32:36eric.araujosetnosy: + eric.araujo
messages: + msg379046
2017-05-12 15:50:55Xophmeistersetmessages: + msg293554
2017-05-12 15:50:05Xophmeistersetpull_requests: + pull_request1654
2017-05-11 13:58:26Xophmeistercreate