diff options
-rw-r--r-- | Doc/library/json.rst | 6 | ||||
-rw-r--r-- | Doc/whatsnew/3.8.rst | 6 | ||||
-rw-r--r-- | Lib/json/tool.py | 16 | ||||
-rw-r--r-- | Lib/test/test_json/test_tool.py | 29 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2018-10-23-14-46-47.bpo-31553.JxRkAW.rst | 1 |
5 files changed, 53 insertions, 5 deletions
diff --git a/Doc/library/json.rst b/Doc/library/json.rst index 510e307..589e86c 100644 --- a/Doc/library/json.rst +++ b/Doc/library/json.rst @@ -717,6 +717,12 @@ Command line options .. versionadded:: 3.5 +.. cmdoption:: --json-lines + + Parse every input line as separate JSON object. + + .. versionadded:: 3.8 + .. cmdoption:: -h, --help Show the help message. diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 51aee1b..3bacbab 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -151,6 +151,12 @@ by right-clicking the button. (Contributed by Tal Einat in :issue:`1529353`.) The changes above have been backported to 3.7 maintenance releases. +json.tool +--------- + +Add option ``--json-lines`` to parse every input line as separate JSON object. +(Contributed by Weipeng Hong in :issue:`31553`.) + os.path ------- diff --git a/Lib/json/tool.py b/Lib/json/tool.py index 5932f4e..1d82bc8 100644 --- a/Lib/json/tool.py +++ b/Lib/json/tool.py @@ -26,19 +26,25 @@ def main(): help='write the output of infile to outfile') parser.add_argument('--sort-keys', action='store_true', default=False, 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') options = parser.parse_args() infile = options.infile or sys.stdin outfile = options.outfile or sys.stdout sort_keys = options.sort_keys - with infile: + json_lines = options.json_lines + with infile, outfile: try: - obj = json.load(infile) + if 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) + outfile.write('\n') except ValueError as e: raise SystemExit(e) - with outfile: - json.dump(obj, outfile, sort_keys=sort_keys, indent=4) - outfile.write('\n') if __name__ == '__main__': diff --git a/Lib/test/test_json/test_tool.py b/Lib/test/test_json/test_tool.py index 9d93f93..1e95bc7 100644 --- a/Lib/test/test_json/test_tool.py +++ b/Lib/test/test_json/test_tool.py @@ -60,6 +60,28 @@ class TestTool(unittest.TestCase): ] """) + jsonlines_raw = textwrap.dedent("""\ + {"ingredients":["frog", "water", "chocolate", "glucose"]} + {"ingredients":["chocolate","steel bolts"]} + """) + + jsonlines_expect = textwrap.dedent("""\ + { + "ingredients": [ + "frog", + "water", + "chocolate", + "glucose" + ] + } + { + "ingredients": [ + "chocolate", + "steel bolts" + ] + } + """) + def test_stdin_stdout(self): args = sys.executable, '-m', 'json.tool' with Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE) as proc: @@ -92,6 +114,13 @@ class TestTool(unittest.TestCase): self.assertEqual(out, b'') self.assertEqual(err, b'') + def test_jsonlines(self): + args = sys.executable, '-m', 'json.tool', '--json-lines' + with Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE) as proc: + out, err = proc.communicate(self.jsonlines_raw.encode()) + self.assertEqual(out.splitlines(), self.jsonlines_expect.encode().splitlines()) + self.assertEqual(err, b'') + def test_help_flag(self): rc, out, err = assert_python_ok('-m', 'json.tool', '-h') self.assertEqual(rc, 0) diff --git a/Misc/NEWS.d/next/Library/2018-10-23-14-46-47.bpo-31553.JxRkAW.rst b/Misc/NEWS.d/next/Library/2018-10-23-14-46-47.bpo-31553.JxRkAW.rst new file mode 100644 index 0000000..de80e7c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-10-23-14-46-47.bpo-31553.JxRkAW.rst @@ -0,0 +1 @@ +Add the --json-lines option to json.tool. Patch by hongweipeng.
\ No newline at end of file |