|
5 | 5 | # terms of the Do What The Fuck You Want To Public License, Version 2, |
6 | 6 | # as published by Sam Hocevar. See the COPYING file for more details. |
7 | 7 |
|
8 | | -from jsonpath_rw import parse |
| 8 | +# Use modern Python |
| 9 | +from __future__ import unicode_literals, print_function, absolute_import |
| 10 | + |
| 11 | +# Standard Library imports |
9 | 12 | import json |
10 | 13 | import sys |
11 | 14 | import glob |
12 | | -if len(sys.argv) < 2: |
13 | | - print("""usage: jsonpath.py expression [files] |
| 15 | +import argparse |
| 16 | + |
| 17 | +# JsonPath-RW imports |
| 18 | +from jsonpath_rw import parse |
14 | 19 |
|
15 | | -The expression is JSONPath and can be: |
| 20 | +def find_matches_for_file(expr, f): |
| 21 | + return expr.find(json.load(f)) |
16 | 22 |
|
17 | | - atomics: |
18 | | - $ - root object |
19 | | - `this` - current object |
| 23 | +def print_matches(matches): |
| 24 | + print('\n'.join(['{0}'.format(match.value) for match in matches])) |
20 | 25 |
|
21 | | - operators: |
22 | | - path1.path2 - same as xpath / |
23 | | - path1|path2 - union |
24 | | - path1..path2 - somewhere in between |
25 | 26 |
|
26 | | - fiels: |
27 | | - fieldname - field with name |
28 | | - * - any field |
29 | | - [_start_?:_end_?] - array slice |
30 | | - [*] - any array index |
31 | | -""") |
32 | | - sys.exit(1) |
| 27 | +def main(*argv): |
| 28 | + parser = argparse.ArgumentParser( |
| 29 | + description='Search JSON files (or stdin) according to a JSONPath expression.', |
| 30 | + formatter_class=argparse.RawTextHelpFormatter, |
| 31 | + epilog=""" |
| 32 | + Quick JSONPath reference (see more at https://github.com/kennknowles/python-jsonpath-rw) |
33 | 33 |
|
34 | | -expr = parse(sys.argv[1]) |
| 34 | + atomics: |
| 35 | + $ - root object |
| 36 | + `this` - current object |
35 | 37 |
|
36 | | -def find_matches_for_file(f): |
37 | | - return [unicode(match.value) for match in expr.find(json.load(f))] |
| 38 | + operators: |
| 39 | + path1.path2 - same as xpath / |
| 40 | + path1|path2 - union |
| 41 | + path1..path2 - somewhere in between |
38 | 42 |
|
39 | | -def print_matches(matches): |
40 | | - print(u"\n".join(matches).encode("utf-8")) |
41 | | - |
42 | | -if len(sys.argv) < 3: |
43 | | - # stdin mode |
44 | | - print_matches(find_matches_for_file(sys.stdin)) |
45 | | -else: |
46 | | - # file paths mode |
47 | | - for pattern in sys.argv[2:]: |
48 | | - for filename in glob.glob(pattern): |
49 | | - with open(filename) as f: |
50 | | - print_matches(find_matches_for_file(f)) |
| 43 | + fields: |
| 44 | + fieldname - field with name |
| 45 | + * - any field |
| 46 | + [_start_?:_end_?] - array slice |
| 47 | + [*] - any array index |
| 48 | + """) |
| 49 | + |
| 50 | + |
| 51 | + |
| 52 | + parser.add_argument('expression', help='A JSONPath expression.') |
| 53 | + parser.add_argument('files', metavar='file', nargs='*', help='Files to search (if none, searches stdin)') |
| 54 | + |
| 55 | + args = parser.parse_args(argv[1:]) |
| 56 | + |
| 57 | + expr = parse(args.expression) |
| 58 | + glob_patterns = args.files |
| 59 | + |
| 60 | + if len(glob_patterns) == 0: |
| 61 | + # stdin mode |
| 62 | + print_matches(find_matches_for_file(expr, sys.stdin)) |
| 63 | + else: |
| 64 | + # file paths mode |
| 65 | + for pattern in glob_patterns: |
| 66 | + for filename in glob.glob(pattern): |
| 67 | + with open(filename) as f: |
| 68 | + print_matches(find_matches_for_file(expr, f)) |
51 | 69 |
|
| 70 | +def entry_point(): |
| 71 | + main(*sys.argv) |
0 commit comments