diff options
-rw-r--r-- | Lib/json/tool.py | 30 | ||||
-rw-r--r-- | Lib/test/test_json/test_tool.py | 41 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2018-02-22-11-24-33.bpo-29636.ogGRE2.rst | 5 |
3 files changed, 69 insertions, 7 deletions
diff --git a/Lib/json/tool.py b/Lib/json/tool.py index b3ef9923e3..6c687d77c5 100644 --- a/Lib/json/tool.py +++ b/Lib/json/tool.py @@ -30,20 +30,36 @@ def main(): help='sort the output of dictionaries alphabetically by key') parser.add_argument('--json-lines', action='store_true', default=False, help='parse input using the jsonlines format') + group = parser.add_mutually_exclusive_group() + group.add_argument('--indent', default=4, type=int, + help='separate items with newlines and use this number ' + 'of spaces for indentation') + group.add_argument('--tab', action='store_const', dest='indent', + const='\t', help='separate items with newlines and use ' + 'tabs for indentation') + group.add_argument('--no-indent', action='store_const', dest='indent', + const=None, + help='separate items with spaces rather than newlines') + group.add_argument('--compact', action='store_true', + help='suppress all whitespace separation (most compact)') options = parser.parse_args() - infile = options.infile - outfile = options.outfile - sort_keys = options.sort_keys - json_lines = options.json_lines - with infile, outfile: + dump_args = { + 'sort_keys': options.sort_keys, + 'indent': options.indent, + } + if options.compact: + dump_args['indent'] = None + dump_args['separators'] = ',', ':' + + with options.infile as infile, options.outfile as outfile: try: - if json_lines: + if options.json_lines: objs = (json.loads(line) for line in infile) else: objs = (json.load(infile), ) for obj in objs: - json.dump(obj, outfile, sort_keys=sort_keys, indent=4) + json.dump(obj, outfile, **dump_args) outfile.write('\n') except ValueError as e: raise SystemExit(e) diff --git a/Lib/test/test_json/test_tool.py b/Lib/test/test_json/test_tool.py index 1e95bc79e5..81d179c6d1 100644 --- a/Lib/test/test_json/test_tool.py +++ b/Lib/test/test_json/test_tool.py @@ -134,3 +134,44 @@ class TestTool(unittest.TestCase): self.assertEqual(out.splitlines(), self.expect_without_sort_keys.encode().splitlines()) self.assertEqual(err, b'') + + def test_indent(self): + json_stdin = b'[1, 2]' + expect = textwrap.dedent('''\ + [ + 1, + 2 + ] + ''').encode() + args = sys.executable, '-m', 'json.tool', '--indent', '2' + with Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE) as proc: + json_stdout, err = proc.communicate(json_stdin) + self.assertEqual(expect.splitlines(), json_stdout.splitlines()) + self.assertEqual(err, b'') + + def test_no_indent(self): + json_stdin = b'[1,\n2]' + expect = b'[1, 2]' + args = sys.executable, '-m', 'json.tool', '--no-indent' + with Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE) as proc: + json_stdout, err = proc.communicate(json_stdin) + self.assertEqual(expect.splitlines(), json_stdout.splitlines()) + self.assertEqual(err, b'') + + def test_tab(self): + json_stdin = b'[1, 2]' + expect = b'[\n\t1,\n\t2\n]\n' + args = sys.executable, '-m', 'json.tool', '--tab' + with Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE) as proc: + json_stdout, err = proc.communicate(json_stdin) + self.assertEqual(expect.splitlines(), json_stdout.splitlines()) + self.assertEqual(err, b'') + + def test_compact(self): + json_stdin = b'[ 1 ,\n 2]' + expect = b'[1,2]' + args = sys.executable, '-m', 'json.tool', '--compact' + with Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE) as proc: + json_stdout, err = proc.communicate(json_stdin) + self.assertEqual(expect.splitlines(), json_stdout.splitlines()) + self.assertEqual(err, b'') diff --git a/Misc/NEWS.d/next/Library/2018-02-22-11-24-33.bpo-29636.ogGRE2.rst b/Misc/NEWS.d/next/Library/2018-02-22-11-24-33.bpo-29636.ogGRE2.rst new file mode 100644 index 0000000000..9f96ed28f9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-22-11-24-33.bpo-29636.ogGRE2.rst @@ -0,0 +1,5 @@ +Add whitespace options for formatting JSON with the ``json.tool`` CLI. The +following mutually exclusive options are now supported: ``--indent`` for +setting the indent level in spaces; ``--tab`` for indenting with tabs; +``--no-indent`` for suppressing newlines; and ``--compact`` for suppressing +all whitespace. The default behavior remains the same as ``--indent=4``. |