TX T
TX T

Reputation: 817

Python script to extract json field

I wrote this little script to extract a specific JSON field passed in from command line. It works and all but it seems inefficient. Any suggestion on any improvement?

jsonx.py name jdoe.json will return "John Doe" jsonx.py rec.course jdoe.json will return "Java"

#!/usr/bin/env python

import sys
import re
import json

def main():
    sys.tracebacklimit = 0

    argc = len(sys.argv)

    if argc == 2:
        field = sys.argv[1]
        infile = sys.stdin

    elif argc == 3:
        field = sys.argv[1]
        infile = open(sys.argv[2], 'rb')

    else:
        raise SystemExit(sys.argv[0] + " <json-field> [ <json-file> ]")

    with infile:
        try:
            obj = json.load(infile)

        except(ValueError, e):
            raise SystemExit(e)

    for f in [f for f in re.split("[\.\[\]]", field) if f != '']:
        try:
            if f.isdigit():
                obj = obj[int(f)]

            else:
                obj = obj[f]

        except(ValueError, e):
            raise SystemExit(e)

    print(obj)

if __name__ == '__main__':
    main()

Sample json file:

{
    "name": "John Doe",
    "rec": {
        "id": 1,
        "course": "Java"
    }
}

Upvotes: 0

Views: 83

Answers (2)

TX T
TX T

Reputation: 817

I added the array handling:

def get_dict(x, field):
    fields = [f for f in re.split("[\.\[\]]", field) if f != '']
    fields = [(int(i) if i.isdigit() else i) for i in fields]
    return reduce(operator.getitem, fields, x)

Upvotes: 0

Binh
Binh

Reputation: 1173

You could use reduce() and operator like this:

x = {"name": "John Doe", "rec": {"id": 1, "course": "Java"}}

from functools import reduce
import operator

def get_dict(mydict, list_attr):
    return reduce(operator.getitem, list_attr, mydict)

Try it out:

>>> get_dict(x, ['rec', 'course'])
Java
>>> get_dict(x, ['name'])
John Doe

Upvotes: 1

Related Questions