Python Working with JSON Files
Table of Contents + β
In the last lesson you learned Working with CSV Files. There you saved data in neat rows and columns. CSV is great for flat tables. But a lot of real data is not flat. It has nesting. Think of a user who has a name, some settings, and a list of friends all bundled together. For that kind of shape, the format you reach for is JSON. This lesson is about reading and writing it in Python.
π€ Why JSON?
Think about the apps you use every day. When WhatsApp talks to its servers, or Netflix loads your watch list, the data flying back and forth is almost always JSON. Config files for your tools are often JSON too.
Here is the pain. You have a Python object in memory, like a dictionary of settings. The moment your program stops, that object is gone. You need a way to write it to a file as plain text. Then you need to read it back later in the same shape.
That is exactly what JSON does. JSON stands for JavaScript Object Notation. It is just a text format for structured data. Python ships with a built-in json module. It turns your objects into JSON text and back. So you do not have to do any of that work by hand.
π§© What JSON Looks Like
JSON is plain text. But it is laid out in a way that holds structure. If you have seen a Python dictionary, JSON will feel familiar right away.
Here is a small piece of JSON describing a user.
{ "name": "Alex", "age": 25, "is_member": true, "hobbies": ["reading", "cycling"]}Look at the pieces:
- The curly braces hold a set of key and value pairs. This is a JSON object.
- The square brackets hold a list of values. This is a JSON array.
- Keys are always text in double quotes, like
"name". - Values can be text, numbers, true or false, or even more objects and arrays inside.
So JSON is really just text that knows how to nest. That nesting is what makes it good for real data.
π The Python and JSON Mapping
Here is the part that makes the json module easy to trust. The two sides line up almost one to one. A Python value becomes a matching JSON value, and back again.
The mapping is worth keeping in front of you.
| Python | JSON |
|---|---|
dict | object (curly braces) |
list | array (square brackets) |
str | string |
int and float | number |
True and False | true and false |
None | null |
The big ones to remember are the first two. A Python dictionary becomes a JSON object. A Python list becomes a JSON array. Get those two and the rest follows naturally.
π¦ dump, load, dumps, loads
The json module gives you these four functions. They sound similar, so people mix them up. But there is a simple way to keep them straight. Just ask yourself a couple of things. Are you going to a file or to a string? And are you saving or loading?
Here is the layout:
json.dumpandjson.loadwork with files.json.dumpsandjson.loadswork with strings. The extrasstands for string.dumpanddumpssave, turning a Python object into JSON.loadandloadsread, turning JSON back into a Python object.
Tip
The s at the end means string. dumps gives you a JSON string. loads reads from a JSON string. No s means it deals with a file instead.
πΎ Saving to a File With json.dump
Letβs start with the most common job. You have a settings dictionary, and you want to save it to a file. The function for that is json.dump.
This program builds a small settings dict and writes it to a file called settings.json.
import json
settings = { "username": "alex", "theme": "dark", "volume": 70, "notifications": True}
with open("settings.json", "w") as file: json.dump(settings, file, indent=4)
print("Settings saved.")Walk through it line by line:
import jsonbrings in the built-in module. You need this at the top.settingsis an ordinary Python dictionary.open("settings.json", "w")opens the file in write mode. Thewithblock closes it for you when it is done.json.dump(settings, file, indent=4)does the real work. It takes the dict, turns it into JSON text, and writes that text into the file.indent=4is optional. It spreads the JSON across lines with neat spacing, so a human can read it.
Output
Settings saved.After running it, the file settings.json on disk holds this text.
{ "username": "alex", "theme": "dark", "volume": 70, "notifications": true}Notice two small changes JSON made for us. The Python True became true, lowercase, because that is how JSON writes it. And the whole thing is laid out neatly thanks to indent=4.
Note
Without indent=4, the JSON gets written all on one line, like {"username": "alex", ...}. It still works perfectly. The indent is only there to make it pleasant for a human to read.
π Loading From a File With json.load
Saving is only half the story. Later, maybe the next time the program runs, you want that settings dict back. That is json.load.
This program opens the file we just wrote and reads it back into a Python dictionary.
import json
with open("settings.json", "r") as file: settings = json.load(file)
print(settings)print("Theme is:", settings["theme"])print("Volume is:", settings["volume"] + 5)Here is what each part does:
open("settings.json", "r")opens the file in read mode.json.load(file)reads the JSON text and rebuilds it as a real Python dictionary.- After that,
settingsis a normal dict again. Sosettings["theme"]works just like any dictionary lookup.
Output
{'username': 'alex', 'theme': 'dark', 'volume': 70, 'notifications': True}Theme is: darkVolume is: 75This is the whole point. The volume came back as a real number 70, not the text "70". So settings["volume"] + 5 does actual math and gives 75. And True came back as a real Python True. The shape and the types survived the trip to the file and back.
π§΅ Working With Strings: dumps and loads
Sometimes the JSON is not in a file at all. It is just text sitting in a variable. This happens a lot with APIs. A web service sends you back a string of JSON, and you need to turn it into a Python object. For that you use the string versions.
First, json.dumps turns a Python object into a JSON string you can hold in a variable.
import json
user = {"name": "Riya", "age": 30, "active": True}
text = json.dumps(user)print(text)print("Type is:", type(text))json.dumps gives back a string instead of writing to a file. So text is now plain JSON text.
Output
{"name": "Riya", "age": 30, "active": true}Type is: <class 'str'>Now the other direction. json.loads takes a JSON string and builds a Python object from it.
import json
incoming = '{"name": "Arjun", "age": 28, "active": false}'
person = json.loads(incoming)print(person)print("Name:", person["name"])print("Active:", person["active"])The variable incoming is a string, the kind of thing an API would hand you. json.loads reads it and gives back a real dictionary.
Output
{'name': 'Arjun', 'age': 28, 'active': False}Name: ArjunActive: FalseSee how JSON false came back as Python False, with the capital F? The mapping table from earlier is working in reverse here.
β οΈ Common Mistakes
A few traps catch people again and again. Watch for these.
- Mixing up the file and string versions.
dump/loadneed a file object.dumps/loadsneed a string. Pass the wrong type and Python complains.
# β Avoid: dumps expects to return a string, not write to a filewith open("data.json", "w") as file: json.dumps(data, file)
# β
Good: dump (no s) writes to a filewith open("data.json", "w") as file: json.dump(data, file)-
Forgetting to
import json. It is built in, but you still have to import it at the top of your file. -
Using single quotes inside a JSON string. JSON keys and text values must use double quotes. Single quotes are valid Python but not valid JSON, so
json.loadswill crash on them.
# β Avoid: single quotes are not valid JSONbad = "{'name': 'Alex'}"json.loads(bad) # crashes
# β
Good: double quotes inside the JSONgood = '{"name": "Alex"}'json.loads(good)- Expecting JSON to save every Python type. JSON only knows the types in the mapping table. Things like a
setor adatetimeare not JSON values, so saving them directly will raise an error. Convert them to a list or a string first.
β Best Practices
Keep these small habits and JSON stays easy.
- Always open files with
with open(...). It closes the file for you, even if something goes wrong partway. - Use
indent=4when a person will read the file. Skip it when only a program will read it, to keep the file small. - Remember the
srule.dumpsandloadsare for strings,dumpandloadare for files. - Keep your data as plain dicts, lists, strings, numbers, and booleans. Those map cleanly to JSON without any extra work.
π§© What Youβve Learned
β JSON is a plain-text format for structured data, used everywhere in APIs and config files.
β A Python dictionary maps to a JSON object, and a Python list maps to a JSON array.
β
json.dump writes a Python object to a file, and json.load reads it back into a Python object.
β
json.dumps and json.loads do the same thing but with strings instead of files. The s means string.
β
Types survive the trip. Numbers come back as numbers, and True/False map to JSON true/false.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
A Python dictionary becomes which JSON type?
Why: A Python dict maps to a JSON object (the curly-brace form), and a Python list maps to a JSON array.
- 2
Which function writes a Python object into a file as JSON?
Why: json.dump (no s) writes to a file. json.dumps returns a string, and the load functions read instead of write.
- 3
What does the extra s in json.dumps and json.loads mean?
Why: The s stands for string. dumps and loads work with JSON strings, while dump and load work with files.
- 4
After json.load reads a JSON number like 70, what does Python give you?
Why: json.load rebuilds the real Python types, so a JSON number comes back as an actual number you can compute with.
π Whatβs Next?
You can now save and load structured data with JSON. Next we look at how Python finds your files in the first place. That way reading and writing them works no matter where your program runs.