Skip to content

Commit ec12559

Browse files
authored
gh-131884: Fix incorrect formatting in json.dumps() when using indent and skipkeys=True (GH-132200)
1 parent 485b499 commit ec12559

File tree

4 files changed

+20
-7
lines changed

4 files changed

+20
-7
lines changed

Lib/json/encoder.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,6 @@ def _iterencode_dict(dct, _current_indent_level):
348348
_current_indent_level += 1
349349
newline_indent = '\n' + _indent * _current_indent_level
350350
item_separator = _item_separator + newline_indent
351-
yield newline_indent
352351
else:
353352
newline_indent = None
354353
item_separator = _item_separator
@@ -381,6 +380,8 @@ def _iterencode_dict(dct, _current_indent_level):
381380
f'not {key.__class__.__name__}')
382381
if first:
383382
first = False
383+
if newline_indent is not None:
384+
yield newline_indent
384385
else:
385386
yield item_separator
386387
yield _encoder(key)
@@ -413,7 +414,7 @@ def _iterencode_dict(dct, _current_indent_level):
413414
except BaseException as exc:
414415
exc.add_note(f'when serializing {type(dct).__name__} item {key!r}')
415416
raise
416-
if newline_indent is not None:
417+
if not first and newline_indent is not None:
417418
_current_indent_level -= 1
418419
yield '\n' + _indent * _current_indent_level
419420
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: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1603,6 +1603,12 @@ encoder_encode_key_value(PyEncoderObject *s, PyUnicodeWriter *writer, bool *firs
16031603

16041604
if (*first) {
16051605
*first = false;
1606+
if (s->indent != Py_None) {
1607+
if (write_newline_indent(writer, indent_level, indent_cache) < 0) {
1608+
Py_DECREF(keystr);
1609+
return -1;
1610+
}
1611+
}
16061612
}
16071613
else {
16081614
if (PyUnicodeWriter_WriteStr(writer, item_separator) < 0) {
@@ -1670,11 +1676,8 @@ encoder_listencode_dict(PyEncoderObject *s, PyUnicodeWriter *writer,
16701676
if (s->indent != Py_None) {
16711677
indent_level++;
16721678
separator = get_item_separator(s, indent_level, indent_cache);
1673-
if (separator == NULL ||
1674-
write_newline_indent(writer, indent_level, indent_cache) < 0)
1675-
{
1679+
if (separator == NULL)
16761680
goto bail;
1677-
}
16781681
}
16791682

16801683
if (s->sort_keys || !PyDict_CheckExact(dct)) {
@@ -1714,7 +1717,7 @@ encoder_listencode_dict(PyEncoderObject *s, PyUnicodeWriter *writer,
17141717
goto bail;
17151718
Py_CLEAR(ident);
17161719
}
1717-
if (s->indent != Py_None) {
1720+
if (s->indent != Py_None && !first) {
17181721
indent_level--;
17191722
if (write_newline_indent(writer, indent_level, indent_cache) < 0) {
17201723
goto bail;

0 commit comments

Comments
 (0)