Skip to content

gh-71549: Add support for JSON serialization of custom types#153607

Draft
serhiy-storchaka wants to merge 3 commits into
python:mainfrom
serhiy-storchaka:json-customize4
Draft

gh-71549: Add support for JSON serialization of custom types#153607
serhiy-storchaka wants to merge 3 commits into
python:mainfrom
serhiy-storchaka:json-customize4

Conversation

@serhiy-storchaka

@serhiy-storchaka serhiy-storchaka commented Jul 12, 2026

Copy link
Copy Markdown
Member

Implements PEP 837: JSON serialization of custom types can be
customized at three levels.

  • A class defines the JSON representation of its instances with the
    new __json__() method.

  • An application registers a serialization function for a type it does
    not control with the new copyreg.json(). The new
    copyreg.RawJSON wrapper includes an already encoded fragment in
    the output verbatim:

    copyreg.json(decimal.Decimal, lambda d: copyreg.RawJSON(str(d)))
    json.dumps({'price': decimal.Decimal('1.10')})  # '{"price": 1.10}'
  • A particular encoder overrides the global registry with the new
    JSONEncoder.dispatch_table attribute, mirroring
    pickle.Pickler.dispatch_table. default= is unchanged and
    runs last.

deque, mappingproxy, ChainMap, UserDict, UserList
and UserString serialize out of the box.

Both encoder implementations are updated with identical semantics, and
the json module gains no new public names. Tests (both
implementations, refleak-clean), docs, NEWS and What's New are
included.

Besides gh-71549, this directly resolves gh-64973, gh-73849 (deque) and
gh-79039 (mappingproxy), and provides the mechanism requested in
gh-79292, gh-114285, gh-86957 (raw output), gh-67312, gh-118810,
gh-145115 (Decimal), gh-70451 (array), gh-67661 (namedtuple), gh-65742
(datetime), gh-75338, gh-78031, gh-83377 (iterables, generators, dict
views) and gh-81022, gh-98306, gh-134717 (float formatting).

PEP: python/peps#5031 (PEP 837, draft)

Discussion: https://discuss.python.org/t/pep-837-extensible-json-serialization/108124

Closes gh-71549.

🤖 Generated with Claude Code

Add the __json__() and __raw_json__() protocol methods, the
copyreg.json() registration function with copyreg.json_dispatch_table,
the copyreg.RawJSON wrapper for including already encoded JSON in the
output verbatim, and the JSONEncoder.dispatch_table attribute for
overriding the global registry per encoder.

Make deque, mappingproxy, ChainMap, UserDict, UserList and UserString
serializable out of the box.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@read-the-docs-community

read-the-docs-community Bot commented Jul 12, 2026

Copy link
Copy Markdown

… docs build

Reset the module context around the object.__json__() and
object.__raw_json__() directives so that they are registered outside
the json namespace, like the dunders in reference/datamodel.rst, and
:meth:`~object.__json__` references from other documents resolve.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

json.dumps to check for obj.__json__ before raising TypeError collections.deque should ship with a stdlib json serializer

1 participant