Skip to content

Commit 7b0bd9e

Browse files
authored
gh-141510, PEP 814: Add frozendict support to json (#144903)
1 parent 347fc43 commit 7b0bd9e

File tree

4 files changed

+20
-6
lines changed

4 files changed

+20
-6
lines changed

Lib/json/encoder.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ class JSONEncoder(object):
7979
+-------------------+---------------+
8080
| Python | JSON |
8181
+===================+===============+
82-
| dict | object |
82+
| dict, frozendict | object |
8383
+-------------------+---------------+
8484
| list, tuple | array |
8585
+-------------------+---------------+
@@ -308,7 +308,7 @@ def _iterencode_list(lst, _current_indent_level):
308308
yield buf
309309
if isinstance(value, (list, tuple)):
310310
chunks = _iterencode_list(value, _current_indent_level)
311-
elif isinstance(value, dict):
311+
elif isinstance(value, (dict, frozendict)):
312312
chunks = _iterencode_dict(value, _current_indent_level)
313313
else:
314314
chunks = _iterencode(value, _current_indent_level)
@@ -395,7 +395,7 @@ def _iterencode_dict(dct, _current_indent_level):
395395
else:
396396
if isinstance(value, (list, tuple)):
397397
chunks = _iterencode_list(value, _current_indent_level)
398-
elif isinstance(value, dict):
398+
elif isinstance(value, (dict, frozendict)):
399399
chunks = _iterencode_dict(value, _current_indent_level)
400400
else:
401401
chunks = _iterencode(value, _current_indent_level)
@@ -429,7 +429,7 @@ def _iterencode(o, _current_indent_level):
429429
yield _floatstr(o)
430430
elif isinstance(o, (list, tuple)):
431431
yield from _iterencode_list(o, _current_indent_level)
432-
elif isinstance(o, dict):
432+
elif isinstance(o, (dict, frozendict)):
433433
yield from _iterencode_dict(o, _current_indent_level)
434434
else:
435435
if markers is not None:

Lib/test/test_json/test_dump.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,18 @@ def test_dump(self):
1212
def test_dumps(self):
1313
self.assertEqual(self.dumps({}), '{}')
1414

15+
def test_dumps_dict(self):
16+
self.assertEqual(self.dumps({'x': 1, 'y': 2}),
17+
'{"x": 1, "y": 2}')
18+
self.assertEqual(self.dumps(frozendict({'x': 1, 'y': 2})),
19+
'{"x": 1, "y": 2}')
20+
lst = [{'x': 1}, frozendict(y=2)]
21+
self.assertEqual(self.dumps(lst),
22+
'[{"x": 1}, {"y": 2}]')
23+
data = {'x': dict(a=1), 'y': frozendict(b=2)}
24+
self.assertEqual(self.dumps(data),
25+
'{"x": {"a": 1}, "y": {"b": 2}}')
26+
1527
def test_dump_skipkeys(self):
1628
v = {b'invalid_key': False, 'valid_key': True}
1729
with self.assertRaises(TypeError):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
The :mod:`json` module now supports the :class:`frozendict` type. Patch by
2+
Victor Stinner.

Modules/_json.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1599,7 +1599,7 @@ encoder_listencode_obj(PyEncoderObject *s, PyUnicodeWriter *writer,
15991599
_Py_LeaveRecursiveCall();
16001600
return rv;
16011601
}
1602-
else if (PyDict_Check(obj)) {
1602+
else if (PyAnyDict_Check(obj)) {
16031603
if (_Py_EnterRecursiveCall(" while encoding a JSON object"))
16041604
return -1;
16051605
rv = encoder_listencode_dict(s, writer, obj, indent_level, indent_cache);
@@ -1838,7 +1838,7 @@ encoder_listencode_dict(PyEncoderObject *s, PyUnicodeWriter *writer,
18381838
goto bail;
18391839
}
18401840

1841-
if (s->sort_keys || !PyDict_CheckExact(dct)) {
1841+
if (s->sort_keys || !PyAnyDict_CheckExact(dct)) {
18421842
PyObject *items = PyMapping_Items(dct);
18431843
if (items == NULL || (s->sort_keys && PyList_Sort(items) < 0)) {
18441844
Py_XDECREF(items);

0 commit comments

Comments
 (0)