0

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"
    }
}
5
  • your requirement is not clear! How jsonx.py name jdoe.json will return "John Doe" ? Commented Apr 5, 2020 at 1:35
  • Why is it inefficient? Commented Apr 5, 2020 at 1:35
  • @Ghanem because it will extract name attribute from jdoe.json Commented Apr 5, 2020 at 1:36
  • @Binh , split the field and loop through. Is there something like obj."${field}". where field could be rec.course... .. Commented Apr 5, 2020 at 2:40
  • @Ghanem, There was typo in the sample json. I just corrected . yes. jsonx.py name will return "John Doe" , see the updated sample json Commented Apr 5, 2020 at 2:42

2 Answers 2

1

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
Sign up to request clarification or add additional context in comments.

Comments

0

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.