man drawing flowchart on whiteboard

Javascript Object Notation, or JSON for short, is a data structure that uses only human-readable text to transfer or store information. It is very popular, especially in the context of web technologies, for transferring data between applications.

JSON allows you to import and export data in a structured manner without doing a lot of work to parse it. Frequently when you interact with a REST API, you will pass JSON structures back and forth. An example of when JSON is used for storing data can be seen in TinyDB. TinyDB stores all the data on disk in the form of JSON. When you work with NOSQL implementations, they generally store the documents in your database as JSON.

How is JSON Structured?

Now that we are clear on what JSON is used for, let’s spend some time talking about how JSON is structured. JSON structure is very simple. It is simply a collection of Key/Value pairs enclosed with some curly braces. Here is an example of a JSON structure of People’s favorite colors:

{
"Bob”:"Green",
"Joe”:"Blue",
“Sally":"Red"
}

As you can see, it is very simple. We have two related strings, separated by a colon, and enclosed in quotes. We separate each pair with a comma. We wrap the entire thing in curly braces.

In the above example, we only used strings. However, JSON supports other data types as well. For example, you can use numbers:

{
"Bob":1,
“Joe":2,
“Sally":3
}

Or, you can use arrays:

{
“Bob":[1,2,3],
“Joe":[4,5,6],
“Sally":[7,8,9] 
}

Finally, you can also nest JSON objects. Here is a JSON document showing everyone’s categorized list of favorite foods

{
“Bob”:{"vegetable":"Broccoli",”dessert",”ice cream”,”bread”:”wheat"},
"Joe":{"vegetable":"Carrot","dessert","Pie","bread":"White"},
“Sally”:{“vegetable”:"Brussel Sprouts","dessert”,”Cake”,”bread”:”Rye"},
}

In the above example, we have a JSON object like this:

{
"vegetable":"Broccoli",
"desert":"ice cream",
"bread":"wheat"
}

But, it is inside a larger JSON document.

In JSON, whitespace does not matter. So we can add line-breaks and extra spaces where we want to make the documents easier to read. We can take our food list example, and re-structure it again:

{
“Bob”:{
“vegetable”:”Broccoli”,
”desert”:”ice cream”,
”bread”:”wheat"
},
“Joe”:{
“vegetable”:”Carrot”,
”desert”:”Pie”,
”bread”:”White"
},
“Sally”:{
“vegetable”:”Brussel Sprouts”,
”desert”:”Cake”,
”bread”:”Rye"
}
}

This example is easier to read in some ways, but it does take a lot more space on the screen. It is really a personal preference on how you want to write it out.

In the next section, we will show code examples, we will discuss how to write and parse these different JSON structures.

How do I use JSON?

In Python, it is very easy to use JSON. Let’s start by using our first example where we listed everyone’s favorite colors. We first import the JSON module a variable and declare a variable to hold our JSON structure:

import json
json_data = '{"Bob":"Green","Joe":"Blue","Sally":"Red"}'
parsed_json = json.loads(json_data)

When we use the json.loads function and pass in our json, it is converted into a dictionary, which makes it easy to look up what color everyone likes

The following code will print out Green, Blue, and Red:

print(parsed_json["Bob"])
print(parsed_json["Joe"])
print(parsed_json["Sally"])

Next, let’s move on to our more complicated JSON structure and look at how we can query a JSON structure with Nested JSON objects.

At first, everything starts off the same:

import json
json_data = ' {"Bob":{"vegetable":"Broccoli","dessert":"ice cream","bread":"wheat"},"Joe":{"vegetable":"Carrot","dessert":"Pie","bread":"White"},"Sally":{"vegetable":"Brussel Sprouts","dessert":"Cake","bread":"Rye"}}'
parsed_json = json.loads(json_data)

But you can see that when we access the nested values, we have to add one more layer. First, we reference the person’s name, then the field from the nested document we wish to access. Below, we will print out Bob’s favorite vegetable, Joe’s favorite dessert, and Sally’s favorite bread:

print(parsed_json["Bob"]["vegetable"])
print(parsed_json["Joe"]["dessert"])
print(parsed_json["Sally"]["bread"])

Something else to note about the JSON object referenced above. Notice it is all one a single line. Earlier I said that JSON does not care how you structure it. And if you are importing it from a file, or receiving a response from a REST endpoint, it does not matter. However, Python cares a lot about spacing and formatting. So it is much easier to keep it all on one line when you are statically setting it in your document. That is not the typical way you work with JSON objects.

At some point, Bob might change his mind about his favorite vegetable. Today, Bob no longer likes Broccoli, instead, he prefers to each spinach. You can easily update the dictionary in a similar fashion to when you queried it to find out Bob’s favorite vegetable:

parsed_json["Bob"]["vegetable"] = "Spinach"

After running the above code, the JSON has been updated to show that Bob’s favorite vegetable is spinach. You can run the print command again to confirm:

print(parsed_json["Bob"]["vegetable"])

Next, we need to track another person’s preferences. To add another key to our JSON structure, you simply call out the key and set a value:

parsed_json["Shirley"]={"vegetable":"Squash","dessert":"Cake","bread":"Sour Dough"}

As you have seen, working with JSON files is almost the same as working with any other collection/container in Python. After converting the JSON string into a dictionary, you can perform all of the various dictionary functions on that object. For more information on working with Python Collections, see our article on Python Collections.

Importing and Exporting JSON files

At this stage, we have our JSON document all nicely constructed, and we want to save it to disk so we can import it next time we run our application. If we start with the above example, you can add the following code to write your json to disk:

f = open('mydata.json', 'w')
f.write(json.dumps(parsed_json))
f.close()

Notice we call the json.dumps function and pass in the parsed_json dictionary. This json.dumps function converts the dictionary back into JSON before we write it to disk. The result is you will have a text file called mydata.json containing everything in your JSON structure:

Screenshot showing contents of JSON file

Next time your application starts up, you need to reload your data into your application. When you read your data, it is a lot like our examples from earlier. You have a bunch of text that you need to parse and ultimately turn into a dictionary. You can accomplish this with the code below:

f = open('mydata.json', 'r')
json_data = f.read()
f.close()
parsed_json = json.loads(json_data)

You can see we open the file, read it into the json_data variable, close the file, then parse the json_data variable. The result is we once again have a dictionary we can query for any of the JSON data we wish to access.

Summary

Today we have discussed how to read and write JSON files. How to lookup and update data stored in JSON documents. And we have looked at some of the things JSON is used for.

Below you can find all of the code examples from above consolidated into one place:

#Import JSON Libraries
import json

#Declare our JSON Object
json_data = ' {"Bob":{"vegetable":"Broccoli","dessert":"ice cream","bread":"wheat"},"Joe":{"vegetable":"Carrot","dessert":"Pie","bread":"White"},"Sally":{"vegetable":"Brussel Sprouts","dessert":"Cake","bread":"Rye"}}'

#Parse our JSON and create a new dictionary object
parsed_json = json.loads(json_data)

#Update Dictionary with new value

parsed_json["Bob"]["vegetable"] = "Spinach"

#Add new key to dictionary
parsed_json["Shirley"]={"vegetable":"Squash","dessert":"Cake","bread":"Sour Dough"}

#Print out values from nested JSON object
print(parsed_json["Bob"]["vegetable"])
print(parsed_json["Joe"]["dessert"])
print(parsed_json["Sally"]["bread"])
print(parsed_json["Shirley"]["dessert"])

#Save JSON to disk

f = open('mydata.json', 'w')
f.write(json.dumps(parsed_json))
f.close()

#Read JSON from disk
f = open('mydata.json', 'r')
json_data = f.read()
f.close()
parsed_json = json.loads(json_data)
print(parsed_json)