Skip to content

Commit 72e7c46

Browse files
roeibenartziserhiy-storchaka
authored andcommitted
[3.13] pythongh-131884: Fix incorrect formatting in json.dumps() when using indent and skipkeys=True (pythonGH-132200)
(cherry picked from commit ec12559) Co-authored-by: Roei Ben Artzi <[email protected]>
1 parent f67dede commit 72e7c46

File tree

4 files changed

+22
-7
lines changed

4 files changed

+22
-7
lines changed

Lib/json/encoder.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,6 @@ def _iterencode_dict(dct, _current_indent_level):
345345
_current_indent_level += 1
346346
newline_indent = '\n' + _indent * _current_indent_level
347347
item_separator = _item_separator + newline_indent
348-
yield newline_indent
349348
else:
350349
newline_indent = None
351350
item_separator = _item_separator
@@ -378,6 +377,8 @@ def _iterencode_dict(dct, _current_indent_level):
378377
f'not {key.__class__.__name__}')
379378
if first:
380379
first = False
380+
if newline_indent is not None:
381+
yield newline_indent
381382
else:
382383
yield item_separator
383384
yield _encoder(key)
@@ -404,7 +405,7 @@ def _iterencode_dict(dct, _current_indent_level):
404405
else:
405406
chunks = _iterencode(value, _current_indent_level)
406407
yield from chunks
407-
if newline_indent is not None:
408+
if not first and newline_indent is not None:
408409
_current_indent_level -= 1
409410
yield '\n' + _indent * _current_indent_level
410411
yield '}'

Lib/test/test_json/test_dump.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ def test_dump_skipkeys(self):
2222
self.assertIn('valid_key', o)
2323
self.assertNotIn(b'invalid_key', o)
2424

25+
def test_dump_skipkeys_indent_empty(self):
26+
v = {b'invalid_key': False}
27+
self.assertEqual(self.json.dumps(v, skipkeys=True, indent=4), '{}')
28+
29+
def test_skipkeys_indent(self):
30+
v = {b'invalid_key': False, 'valid_key': True}
31+
self.assertEqual(self.json.dumps(v, skipkeys=True, indent=4), '{\n "valid_key": true\n}')
32+
2533
def test_encode_truefalse(self):
2634
self.assertEqual(self.dumps(
2735
{True: False, False: True}, sort_keys=True),
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix formatting issues in :func:`json.dump` when both *indent* and *skipkeys* are used.

Modules/_json.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,6 +1514,12 @@ encoder_encode_key_value(PyEncoderObject *s, _PyUnicodeWriter *writer, bool *fir
15141514

15151515
if (*first) {
15161516
*first = false;
1517+
if (s->indent != Py_None) {
1518+
if (_PyUnicodeWriter_WriteStr(writer, newline_indent) < 0) {
1519+
Py_DECREF(keystr);
1520+
return -1;
1521+
}
1522+
}
15171523
}
15181524
else {
15191525
if (_PyUnicodeWriter_WriteStr(writer, item_separator) < 0) {
@@ -1586,9 +1592,6 @@ encoder_listencode_dict(PyEncoderObject *s, _PyUnicodeWriter *writer,
15861592
}
15871593
// update item separator with a borrowed reference
15881594
current_item_separator = separator_indent;
1589-
if (_PyUnicodeWriter_WriteStr(writer, new_newline_indent) < 0) {
1590-
goto bail;
1591-
}
15921595
}
15931596

15941597
if (s->sort_keys || !PyDict_CheckExact(dct)) {
@@ -1632,8 +1635,10 @@ encoder_listencode_dict(PyEncoderObject *s, _PyUnicodeWriter *writer,
16321635
Py_CLEAR(new_newline_indent);
16331636
Py_CLEAR(separator_indent);
16341637

1635-
if (_PyUnicodeWriter_WriteStr(writer, newline_indent) < 0) {
1636-
goto bail;
1638+
if (!first) {
1639+
if (_PyUnicodeWriter_WriteStr(writer, newline_indent) < 0) {
1640+
goto bail;
1641+
}
16371642
}
16381643
}
16391644

0 commit comments

Comments
 (0)