Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Closed
46 changes: 35 additions & 11 deletions 46 Lib/json/tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,25 @@
import json
import sys

def parse_json_from_filehandle(infile, sort_keys):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These functions are a bit repetitive and add a lot of unnecessary lines of code. I think they could be avoided by keeping the functionality in the original location. The code could become more like:

sort_keys = options.sort_keys
jsonlines = options.jsonlines
with infile:
    if jsonlines:
        if sort_keys:
            objs = [json.loads(line) for line in infile]
        else:
           ...
    else:
        if sort_keys:
            objs = [json.load(infile)]
        else:
            ...

This keeps the code more concise.

try:
if sort_keys:
return json.load(infile)
else:
return json.load(infile,
object_pairs_hook=collections.OrderedDict)
except ValueError as e:
raise SystemExit(e)

def parse_json_from_string(input, sort_keys):
try:
if sort_keys:
return json.loads(input)
else:
return json.loads(input,
object_pairs_hook=collections.OrderedDict)
except ValueError as e:
raise SystemExit(e)

def main():
prog = 'python -m json.tool'
Expand All @@ -27,23 +46,28 @@ 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('--jsonlines', 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:
try:
if sort_keys:
obj = json.load(infile)
else:
obj = json.load(infile,
object_pairs_hook=collections.OrderedDict)
except ValueError as e:
raise SystemExit(e)
jsonlines = options.jsonlines
objs = []

if jsonlines:
with infile:
for line in infile:
objs.append(parse_json_from_string(line, sort_keys))
else:
with infile:
objs = [parse_json_from_filehandle(infile, sort_keys)]

with outfile:
json.dump(obj, outfile, sort_keys=sort_keys, indent=4)
outfile.write('\n')
for obj in objs:
json.dump(obj, outfile, sort_keys=sort_keys, indent=4)
outfile.write('\n')


if __name__ == '__main__':
Expand Down
28 changes: 28 additions & 0 deletions 28 Lib/test/test_json/test_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,27 @@ class TestTool(unittest.TestCase):
]
""")

jsonlines_data = """\
{"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:
Expand Down Expand Up @@ -92,6 +113,13 @@ def test_infile_outfile(self):
self.assertEqual(out, b'')
self.assertEqual(err, b'')

def test_jsonlines(self):
args = sys.executable, '-m', 'json.tool', '--jsonlines'
with Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE) as proc:
out, err = proc.communicate(self.jsonlines_data.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)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Add the --jsonlines option to json.tool in order to be able to parse input
sent using the jsonlines format.
Morty Proxy This is a proxified and sanitized view of the page, visit original site.