Skip to content

Commit 0325794

Browse files
dhimmelmethane
authored andcommitted
bpo-29636: Add --(no-)indent arguments to json.tool (GH-345)
1 parent eb48a45 commit 0325794

File tree

3 files changed

+69
-7
lines changed

3 files changed

+69
-7
lines changed

Lib/json/tool.py

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,36 @@ def main():
3030
help='sort the output of dictionaries alphabetically by key')
3131
parser.add_argument('--json-lines', action='store_true', default=False,
3232
help='parse input using the jsonlines format')
33+
group = parser.add_mutually_exclusive_group()
34+
group.add_argument('--indent', default=4, type=int,
35+
help='separate items with newlines and use this number '
36+
'of spaces for indentation')
37+
group.add_argument('--tab', action='store_const', dest='indent',
38+
const='\t', help='separate items with newlines and use '
39+
'tabs for indentation')
40+
group.add_argument('--no-indent', action='store_const', dest='indent',
41+
const=None,
42+
help='separate items with spaces rather than newlines')
43+
group.add_argument('--compact', action='store_true',
44+
help='suppress all whitespace separation (most compact)')
3345
options = parser.parse_args()
3446

35-
infile = options.infile
36-
outfile = options.outfile
37-
sort_keys = options.sort_keys
38-
json_lines = options.json_lines
39-
with infile, outfile:
47+
dump_args = {
48+
'sort_keys': options.sort_keys,
49+
'indent': options.indent,
50+
}
51+
if options.compact:
52+
dump_args['indent'] = None
53+
dump_args['separators'] = ',', ':'
54+
55+
with options.infile as infile, options.outfile as outfile:
4056
try:
41-
if json_lines:
57+
if options.json_lines:
4258
objs = (json.loads(line) for line in infile)
4359
else:
4460
objs = (json.load(infile), )
4561
for obj in objs:
46-
json.dump(obj, outfile, sort_keys=sort_keys, indent=4)
62+
json.dump(obj, outfile, **dump_args)
4763
outfile.write('\n')
4864
except ValueError as e:
4965
raise SystemExit(e)

Lib/test/test_json/test_tool.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,3 +134,44 @@ def test_sort_keys_flag(self):
134134
self.assertEqual(out.splitlines(),
135135
self.expect_without_sort_keys.encode().splitlines())
136136
self.assertEqual(err, b'')
137+
138+
def test_indent(self):
139+
json_stdin = b'[1, 2]'
140+
expect = textwrap.dedent('''\
141+
[
142+
1,
143+
2
144+
]
145+
''').encode()
146+
args = sys.executable, '-m', 'json.tool', '--indent', '2'
147+
with Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE) as proc:
148+
json_stdout, err = proc.communicate(json_stdin)
149+
self.assertEqual(expect.splitlines(), json_stdout.splitlines())
150+
self.assertEqual(err, b'')
151+
152+
def test_no_indent(self):
153+
json_stdin = b'[1,\n2]'
154+
expect = b'[1, 2]'
155+
args = sys.executable, '-m', 'json.tool', '--no-indent'
156+
with Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE) as proc:
157+
json_stdout, err = proc.communicate(json_stdin)
158+
self.assertEqual(expect.splitlines(), json_stdout.splitlines())
159+
self.assertEqual(err, b'')
160+
161+
def test_tab(self):
162+
json_stdin = b'[1, 2]'
163+
expect = b'[\n\t1,\n\t2\n]\n'
164+
args = sys.executable, '-m', 'json.tool', '--tab'
165+
with Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE) as proc:
166+
json_stdout, err = proc.communicate(json_stdin)
167+
self.assertEqual(expect.splitlines(), json_stdout.splitlines())
168+
self.assertEqual(err, b'')
169+
170+
def test_compact(self):
171+
json_stdin = b'[ 1 ,\n 2]'
172+
expect = b'[1,2]'
173+
args = sys.executable, '-m', 'json.tool', '--compact'
174+
with Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE) as proc:
175+
json_stdout, err = proc.communicate(json_stdin)
176+
self.assertEqual(expect.splitlines(), json_stdout.splitlines())
177+
self.assertEqual(err, b'')
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Add whitespace options for formatting JSON with the ``json.tool`` CLI. The
2+
following mutually exclusive options are now supported: ``--indent`` for
3+
setting the indent level in spaces; ``--tab`` for indenting with tabs;
4+
``--no-indent`` for suppressing newlines; and ``--compact`` for suppressing
5+
all whitespace. The default behavior remains the same as ``--indent=4``.

0 commit comments

Comments
 (0)