A document from MCS 275 Spring 2022, instructor David Dumas. You can also get the notebook file.

# MCS 275 Spring 2022 Homework 9 Solution¶

• Course Instructor: David Dumas
• Solutions prepared by: Johnny Joyce

## Instructions:¶

• Complete the problems below, which ask you to write Python scripts.
• Upload your python code directly to gradescope, i.e. upload the .py files containing your work. (If you upload a screenshot or other file format, you won't get credit.)

### Deadline¶

This homework assignment must be submitted in Gradescope by Noon central time on Tuesday 15 March 2022.

### Collaboration¶

Collaboration is prohibited, and you may only access resources (books, online, etc.) listed below.

### Resources you may consult¶

The course materials you may refer to for this homework are:

### Point distribution¶

This homework assignment has a single problem, called Problem 2. The grading breakdown is:

Points Item
2 Autograder
4 Problem 2
6 Total

The part marked "autograder" reflects points assigned to your submission based on some simple automated checks for Python syntax, etc.. The result of these checks is shown immediately after you submit.

### What to do if you're stuck¶

Ask your instructor or TA a question by email, in office hours, or on discord.

## Problem 2: JSON key list¶

Make a program hwk9.py that reads a JSON file specified as the first command line argument, and which prints a list of all the keys that appear in any of the nested objects in that file. You can assume that JSON contains only numbers, strings, null (the JSON value that becomes Python's None), and objects (which Python converts to dictionaries); it will not contain any lists.

For example, if the JSON file contains

{
"slinky": {
"green": 11,
"friend": {
"slinky": 2,
"graft": 12.5
},
"plus": "grand"
},
"present": {
"saucer": "orange",
"brand": 97.5
},
"nonce": null
}

then the output might be:

slinky
green
friend
graft
plus
present
saucer
brand
nonce

It would be acceptable for the same list of keys to be printed in a different order.

Notice that even if a key is used in several places, it only appears once in the output list. Since you only want to keep track of distinct keys, make proper use of Python set object to keep track of the keys that have been seen.

Since you'll need to traverse the nested objects within the JSON file looking for keys, this problem is a natural candidate for recursion. Keep in mind that if any value is a dict, then further recursion is needed to expore its keys. If the value is not dict, then there is no need to search further.

### Reminder¶

If you ever find yourself writing

for k in d.keys():

where d is a dict, you can and should replace it with the equivalent but simpler

for k in d:

In fact, whenever you treat a dict as an iterable, the items you iterate over are the keys! This usually means that calling .keys() is unnecessary.

# Solution¶

A recursive function to find all keys:

In [1]:
def find_keys(d):
'''Recursively finds all keys in dict d, including those inside dicts inside d'''

keys_set = set() # Use set() so we don't keep duplicates

for key in d:

keys_set.add(key)

val = d[key] # Get value corresponding to key
if isinstance(val, dict): # If value is itself a dict, then make a recursive call
keys_set.update(find_keys(val))

return keys_set

Tester code to open up the example json file and call the recursive function:

In [2]:
import json
import sys

if len(sys.argv) < 2:
print("Please enter a json file name as a command line arg")
exit()

with open(sys.argv[1], "r") as f:
d = json.load(f)

print(find_keys(d))
{'present', 'saucer', 'friend', 'plus', 'graft', 'slinky', 'brand', 'nonce', 'green'}