1*cda5da8dSAndroid Build Coastguard Workerr"""Command-line tool to validate and pretty-print JSON 2*cda5da8dSAndroid Build Coastguard Worker 3*cda5da8dSAndroid Build Coastguard WorkerUsage:: 4*cda5da8dSAndroid Build Coastguard Worker 5*cda5da8dSAndroid Build Coastguard Worker $ echo '{"json":"obj"}' | python -m json.tool 6*cda5da8dSAndroid Build Coastguard Worker { 7*cda5da8dSAndroid Build Coastguard Worker "json": "obj" 8*cda5da8dSAndroid Build Coastguard Worker } 9*cda5da8dSAndroid Build Coastguard Worker $ echo '{ 1.2:3.4}' | python -m json.tool 10*cda5da8dSAndroid Build Coastguard Worker Expecting property name enclosed in double quotes: line 1 column 3 (char 2) 11*cda5da8dSAndroid Build Coastguard Worker 12*cda5da8dSAndroid Build Coastguard Worker""" 13*cda5da8dSAndroid Build Coastguard Workerimport argparse 14*cda5da8dSAndroid Build Coastguard Workerimport json 15*cda5da8dSAndroid Build Coastguard Workerimport sys 16*cda5da8dSAndroid Build Coastguard Workerfrom pathlib import Path 17*cda5da8dSAndroid Build Coastguard Worker 18*cda5da8dSAndroid Build Coastguard Worker 19*cda5da8dSAndroid Build Coastguard Workerdef main(): 20*cda5da8dSAndroid Build Coastguard Worker prog = 'python -m json.tool' 21*cda5da8dSAndroid Build Coastguard Worker description = ('A simple command line interface for json module ' 22*cda5da8dSAndroid Build Coastguard Worker 'to validate and pretty-print JSON objects.') 23*cda5da8dSAndroid Build Coastguard Worker parser = argparse.ArgumentParser(prog=prog, description=description) 24*cda5da8dSAndroid Build Coastguard Worker parser.add_argument('infile', nargs='?', 25*cda5da8dSAndroid Build Coastguard Worker type=argparse.FileType(encoding="utf-8"), 26*cda5da8dSAndroid Build Coastguard Worker help='a JSON file to be validated or pretty-printed', 27*cda5da8dSAndroid Build Coastguard Worker default=sys.stdin) 28*cda5da8dSAndroid Build Coastguard Worker parser.add_argument('outfile', nargs='?', 29*cda5da8dSAndroid Build Coastguard Worker type=Path, 30*cda5da8dSAndroid Build Coastguard Worker help='write the output of infile to outfile', 31*cda5da8dSAndroid Build Coastguard Worker default=None) 32*cda5da8dSAndroid Build Coastguard Worker parser.add_argument('--sort-keys', action='store_true', default=False, 33*cda5da8dSAndroid Build Coastguard Worker help='sort the output of dictionaries alphabetically by key') 34*cda5da8dSAndroid Build Coastguard Worker parser.add_argument('--no-ensure-ascii', dest='ensure_ascii', action='store_false', 35*cda5da8dSAndroid Build Coastguard Worker help='disable escaping of non-ASCII characters') 36*cda5da8dSAndroid Build Coastguard Worker parser.add_argument('--json-lines', action='store_true', default=False, 37*cda5da8dSAndroid Build Coastguard Worker help='parse input using the JSON Lines format. ' 38*cda5da8dSAndroid Build Coastguard Worker 'Use with --no-indent or --compact to produce valid JSON Lines output.') 39*cda5da8dSAndroid Build Coastguard Worker group = parser.add_mutually_exclusive_group() 40*cda5da8dSAndroid Build Coastguard Worker group.add_argument('--indent', default=4, type=int, 41*cda5da8dSAndroid Build Coastguard Worker help='separate items with newlines and use this number ' 42*cda5da8dSAndroid Build Coastguard Worker 'of spaces for indentation') 43*cda5da8dSAndroid Build Coastguard Worker group.add_argument('--tab', action='store_const', dest='indent', 44*cda5da8dSAndroid Build Coastguard Worker const='\t', help='separate items with newlines and use ' 45*cda5da8dSAndroid Build Coastguard Worker 'tabs for indentation') 46*cda5da8dSAndroid Build Coastguard Worker group.add_argument('--no-indent', action='store_const', dest='indent', 47*cda5da8dSAndroid Build Coastguard Worker const=None, 48*cda5da8dSAndroid Build Coastguard Worker help='separate items with spaces rather than newlines') 49*cda5da8dSAndroid Build Coastguard Worker group.add_argument('--compact', action='store_true', 50*cda5da8dSAndroid Build Coastguard Worker help='suppress all whitespace separation (most compact)') 51*cda5da8dSAndroid Build Coastguard Worker options = parser.parse_args() 52*cda5da8dSAndroid Build Coastguard Worker 53*cda5da8dSAndroid Build Coastguard Worker dump_args = { 54*cda5da8dSAndroid Build Coastguard Worker 'sort_keys': options.sort_keys, 55*cda5da8dSAndroid Build Coastguard Worker 'indent': options.indent, 56*cda5da8dSAndroid Build Coastguard Worker 'ensure_ascii': options.ensure_ascii, 57*cda5da8dSAndroid Build Coastguard Worker } 58*cda5da8dSAndroid Build Coastguard Worker if options.compact: 59*cda5da8dSAndroid Build Coastguard Worker dump_args['indent'] = None 60*cda5da8dSAndroid Build Coastguard Worker dump_args['separators'] = ',', ':' 61*cda5da8dSAndroid Build Coastguard Worker 62*cda5da8dSAndroid Build Coastguard Worker with options.infile as infile: 63*cda5da8dSAndroid Build Coastguard Worker try: 64*cda5da8dSAndroid Build Coastguard Worker if options.json_lines: 65*cda5da8dSAndroid Build Coastguard Worker objs = (json.loads(line) for line in infile) 66*cda5da8dSAndroid Build Coastguard Worker else: 67*cda5da8dSAndroid Build Coastguard Worker objs = (json.load(infile),) 68*cda5da8dSAndroid Build Coastguard Worker 69*cda5da8dSAndroid Build Coastguard Worker if options.outfile is None: 70*cda5da8dSAndroid Build Coastguard Worker out = sys.stdout 71*cda5da8dSAndroid Build Coastguard Worker else: 72*cda5da8dSAndroid Build Coastguard Worker out = options.outfile.open('w', encoding='utf-8') 73*cda5da8dSAndroid Build Coastguard Worker with out as outfile: 74*cda5da8dSAndroid Build Coastguard Worker for obj in objs: 75*cda5da8dSAndroid Build Coastguard Worker json.dump(obj, outfile, **dump_args) 76*cda5da8dSAndroid Build Coastguard Worker outfile.write('\n') 77*cda5da8dSAndroid Build Coastguard Worker except ValueError as e: 78*cda5da8dSAndroid Build Coastguard Worker raise SystemExit(e) 79*cda5da8dSAndroid Build Coastguard Worker 80*cda5da8dSAndroid Build Coastguard Worker 81*cda5da8dSAndroid Build Coastguard Workerif __name__ == '__main__': 82*cda5da8dSAndroid Build Coastguard Worker try: 83*cda5da8dSAndroid Build Coastguard Worker main() 84*cda5da8dSAndroid Build Coastguard Worker except BrokenPipeError as exc: 85*cda5da8dSAndroid Build Coastguard Worker sys.exit(exc.errno) 86