gh-141510, PEP 814: Add frozendict support to json (#144903)

This commit is contained in:
Victor Stinner 2026-02-21 12:22:47 +01:00 committed by GitHub
parent 347fc438cf
commit 7b0bd9eb91
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 20 additions and 6 deletions

View file

@ -79,7 +79,7 @@ class JSONEncoder(object):
+-------------------+---------------+
| Python | JSON |
+===================+===============+
| dict | object |
| dict, frozendict | object |
+-------------------+---------------+
| list, tuple | array |
+-------------------+---------------+
@ -308,7 +308,7 @@ def _iterencode_list(lst, _current_indent_level):
yield buf
if isinstance(value, (list, tuple)):
chunks = _iterencode_list(value, _current_indent_level)
elif isinstance(value, dict):
elif isinstance(value, (dict, frozendict)):
chunks = _iterencode_dict(value, _current_indent_level)
else:
chunks = _iterencode(value, _current_indent_level)
@ -395,7 +395,7 @@ def _iterencode_dict(dct, _current_indent_level):
else:
if isinstance(value, (list, tuple)):
chunks = _iterencode_list(value, _current_indent_level)
elif isinstance(value, dict):
elif isinstance(value, (dict, frozendict)):
chunks = _iterencode_dict(value, _current_indent_level)
else:
chunks = _iterencode(value, _current_indent_level)
@ -429,7 +429,7 @@ def _iterencode(o, _current_indent_level):
yield _floatstr(o)
elif isinstance(o, (list, tuple)):
yield from _iterencode_list(o, _current_indent_level)
elif isinstance(o, dict):
elif isinstance(o, (dict, frozendict)):
yield from _iterencode_dict(o, _current_indent_level)
else:
if markers is not None:

View file

@ -12,6 +12,18 @@ def test_dump(self):
def test_dumps(self):
self.assertEqual(self.dumps({}), '{}')
def test_dumps_dict(self):
self.assertEqual(self.dumps({'x': 1, 'y': 2}),
'{"x": 1, "y": 2}')
self.assertEqual(self.dumps(frozendict({'x': 1, 'y': 2})),
'{"x": 1, "y": 2}')
lst = [{'x': 1}, frozendict(y=2)]
self.assertEqual(self.dumps(lst),
'[{"x": 1}, {"y": 2}]')
data = {'x': dict(a=1), 'y': frozendict(b=2)}
self.assertEqual(self.dumps(data),
'{"x": {"a": 1}, "y": {"b": 2}}')
def test_dump_skipkeys(self):
v = {b'invalid_key': False, 'valid_key': True}
with self.assertRaises(TypeError):

View file

@ -0,0 +1,2 @@
The :mod:`json` module now supports the :class:`frozendict` type. Patch by
Victor Stinner.

View file

@ -1599,7 +1599,7 @@ encoder_listencode_obj(PyEncoderObject *s, PyUnicodeWriter *writer,
_Py_LeaveRecursiveCall();
return rv;
}
else if (PyDict_Check(obj)) {
else if (PyAnyDict_Check(obj)) {
if (_Py_EnterRecursiveCall(" while encoding a JSON object"))
return -1;
rv = encoder_listencode_dict(s, writer, obj, indent_level, indent_cache);
@ -1838,7 +1838,7 @@ encoder_listencode_dict(PyEncoderObject *s, PyUnicodeWriter *writer,
goto bail;
}
if (s->sort_keys || !PyDict_CheckExact(dct)) {
if (s->sort_keys || !PyAnyDict_CheckExact(dct)) {
PyObject *items = PyMapping_Items(dct);
if (items == NULL || (s->sort_keys && PyList_Sort(items) < 0)) {
Py_XDECREF(items);