Skip to content

Commit e2a9a3f

Browse files
[3.13] gh-131884: Fix incorrect formatting in json.dumps() when using indent and skipkeys=True (GH-132200) (GH-135061)
(cherry picked from commit ec12559) Co-authored-by: Roei Ben Artzi <155478676+roeibenartzi@users.noreply.github.com>
1 parent 5a69d4f commit e2a9a3f

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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy