How to create a JSON file in Python

Learn how to create a JSON file in Python. This guide covers different methods, tips, real-world applications, and common error debugging.

How to create a JSON file in Python
Published on: 
Thu
Feb 12, 2026
Updated on: 
Tue
Feb 24, 2026
The Replit Team Logo Image
The Replit Team

Python makes it simple to create JSON files, a key task for data exchange and configuration. The built-in json module converts Python objects to the JSON format with minimal code.

Here, you’ll find techniques, practical tips, and real-world applications. You'll also get advice on how to debug your code, so you can confidently handle JSON data in your projects.

Creating a JSON file with json.dump()

import json

data = {"name": "John", "age": 30, "city": "New York"}
with open("data.json", "w") as file:
   json.dump(data, file)--OUTPUT--# No output, but a data.json file is created with content:
# {"name": "John", "age": 30, "city": "New York"}

The json.dump() function directly serializes a Python object into a file stream. It requires two main arguments: the Python object to convert, like the data dictionary, and the file object to write to. This combines serialization and writing into one step.

The with open() statement manages the file. Using "w" for write mode is a key detail. It creates the file if it doesn't exist or completely overwrites it if it does, ensuring your JSON file always reflects the latest data.

Basic techniques for JSON file creation

While json.dump() writes directly to a file, you can gain more control by generating JSON strings, handling nested data, and managing file encoding.

Using json.dumps() to generate JSON strings

import json

data = {"name": "Alice", "age": 25, "city": "Boston"}
json_string = json.dumps(data)
with open("data_string.json", "w") as file:
   file.write(json_string)--OUTPUT--# No output, but a data_string.json file is created with content:
# {"name": "Alice", "age": 25, "city": "Boston"}

The json.dumps() function converts a Python object into a JSON formatted string. Unlike json.dump(), this method doesn't write directly to a file. Instead, it returns the JSON data as a string variable, which gives you more control over the output.

You can then use this string in various ways before saving:

  • Log the JSON output for debugging.
  • Send the data over a network.
  • Write it to a file using file.write(), as the example does.

Working with nested data structures

import json

user = {
   "name": "Bob",
   "address": {"street": "123 Main St", "city": "Chicago"},
   "hobbies": ["reading", "swimming", "coding"]
}
with open("nested_data.json", "w") as file:
   json.dump(user, file)--OUTPUT--# No output, but a nested_data.json file is created with content:
# {"name": "Bob", "address": {"street": "123 Main St", "city": "Chicago"}, "hobbies": ["reading", "swimming", "coding"]}

Python's json module handles complex data structures without extra effort. The user dictionary in this example contains other structures within it—a nested dictionary for the address and a list for hobbies. You don't need any special code to process them.

  • The nested address dictionary becomes a JSON object.
  • The hobbies list becomes a JSON array.

When you call json.dump(), it automatically converts these Python types into their correct JSON equivalents, simplifying the serialization of intricate data.

Handling file encoding options

import json

data = {"name": "Carlos", "description": "Loves café au lait ☕"}
with open("unicode_data.json", "w", encoding="utf-8") as file:
   json.dump(data, file, ensure_ascii=False)--OUTPUT--# No output, but a unicode_data.json file is created with proper UTF-8 encoding:
# {"name": "Carlos", "description": "Loves café au lait ☕"}

When your data includes special characters or emojis, you need to specify the file's encoding. Using encoding="utf-8" with the open() function ensures the file correctly saves characters beyond the standard English alphabet.

This works with a key parameter in json.dump():

  • By default, Python escapes non-ASCII characters, turning them into sequences like \u2615.
  • Setting ensure_ascii=False tells the function to write characters like "é" and "☕" directly, making your JSON file more human-readable.

Advanced JSON file handling

With the basics in hand, you're ready to tackle advanced formatting and serialize custom Python objects that the json module doesn't handle by default.

Creating formatted JSON with indent and sort_keys

import json

data = {"z": 1, "b": 2, "a": 3, "nested": {"x": 1, "y": 2}}
with open("formatted.json", "w") as file:
   json.dump(data, file, indent=4, sort_keys=True)--OUTPUT--# No output, but a formatted.json file is created with content:
# {
#     "a": 3,
#     "b": 2,
#     "nested": {
#         "x": 1,
#         "y": 2
#     },
#     "z": 1
# }

You can make your JSON files much more readable by passing optional arguments to json.dump(). This formatting is a lifesaver for debugging or when you need to inspect a file's contents manually. Two key parameters control this:

  • The indent=4 parameter tells the function to pretty-print the output, using four spaces for each level of nesting.
  • Setting sort_keys=True organizes the dictionary keys alphabetically, which creates a predictable structure that's helpful for comparing files.

Custom object serialization with the default parameter

import json
from datetime import datetime

def serialize_datetime(obj):
   if isinstance(obj, datetime):
       return obj.isoformat()
   raise TypeError("Type not serializable")

data = {"name": "Event", "timestamp": datetime.now()}
with open("custom_objects.json", "w") as file:
   json.dump(data, file, default=serialize_datetime)--OUTPUT--# No output, but a custom_objects.json file is created with content:
# {"name": "Event", "timestamp": "2023-04-15T14:30:45.123456"}

The json module can't serialize complex Python objects like datetime out of the box, which would normally raise a TypeError. The default parameter in json.dump() provides a custom fallback for these unsupported types. You pass it a function that acts as a special converter.

  • When json.dump() encounters an object it doesn't recognize, it calls your function with that object.
  • Here, the serialize_datetime function converts the datetime object into a string using isoformat(), a format that JSON can easily handle.

Using JSONEncoder for complex serialization

import json
from datetime import datetime

class CustomEncoder(json.JSONEncoder):
   def default(self, obj):
       if isinstance(obj, datetime):
           return {"__datetime__": obj.isoformat()}
       return super().default(obj)

data = {"event": "Meeting", "when": datetime.now()}
with open("encoder.json", "w") as file:
   json.dump(data, file, cls=CustomEncoder, indent=2)--OUTPUT--# No output, but an encoder.json file is created with content:
# {
#   "event": "Meeting",
#   "when": {
#     "__datetime__": "2023-04-15T14:30:45.123456"
#   }
# }

For more complex serialization, subclassing json.JSONEncoder provides a structured and reusable solution. By creating a custom class and overriding its default method, you can define how to handle types the json module doesn't recognize on its own.

  • The default method is where you convert objects like datetime into a JSON-friendly format.
  • You then pass your custom class to json.dump() using the cls parameter.

This approach keeps your serialization logic organized, which is especially useful in larger projects where consistency is key.

Move faster with Replit

Replit is an AI-powered development platform that transforms natural language into working applications. Describe what you want to build, and Replit Agent creates it—complete with databases, APIs, and deployment.

For the JSON creation techniques we've explored, Replit Agent can turn them into production-ready tools:

  • Build a configuration file generator that uses indent and sort_keys to create clean, human-readable settings files.
  • Create a data export utility that serializes complex, nested Python objects into a structured JSON format for backups or data sharing.
  • Deploy an event logging service that automatically converts datetime objects into standardized ISO format strings within JSON logs.

Describe your app idea, and Replit Agent writes the code, tests it, and fixes issues automatically, all in your browser.

Common errors and challenges

Creating JSON files is usually straightforward, but you can run into a few common snags like type errors or incorrect file handling.

Handling non-serializable types with json.dump()

A frequent issue is the TypeError that pops up when json.dump() encounters data it can't convert, such as datetime objects or your own custom classes. The JSON format has a limited set of data types, and these complex objects aren't on the list.

To fix this, you need to provide a translation guide. You can do this by passing a special function to the default parameter or by using a custom JSONEncoder class to define how these objects should be turned into a JSON-compatible format, like a string.

Fixing incorrect file modes with json.dump()

Your choice of file mode in the open() function is critical. Using the wrong one can lead to corrupted files or errors. For instance, opening a file in append mode ("a") will tack your new JSON onto the end of an existing file, creating an invalid structure with multiple top-level objects.

Similarly, trying to write to a file opened in read mode ("r") will cause an error. To avoid these problems, always use write mode ("w") when you intend to create a new JSON file or completely replace an old one. This ensures you start with a clean slate every time.

Handling special characters encoding in json.dump()

If your JSON output contains strange escape sequences like \u20ac instead of the "€" symbol, you've run into an encoding issue. By default, the json module escapes all non-ASCII characters, which is safe but not very readable. In some cases, it can even lead to a UnicodeEncodeError.

The solution involves two steps. First, open your file with the correct encoding by specifying encoding="utf-8". Second, tell json.dump() to write the characters as-is by setting ensure_ascii=False. This combination correctly handles everything from accented letters to emojis.

Handling non-serializable types with json.dump()

You'll hit a TypeError if you pass an object to json.dump() that it can't recognize, like a datetime object. Since the JSON standard doesn't include a date type, Python's json module stops. See what happens in this example.

import json
from datetime import datetime

event = {"name": "Conference", "date": datetime.now()}
with open("event.json", "w") as file:
   json.dump(event, file)

The datetime.now() object in the event dictionary isn't a standard JSON type, so json.dump() doesn't know how to convert it. This mismatch triggers the TypeError. Check out the following code for a solution.

import json
from datetime import datetime

event = {"name": "Conference", "date": datetime.now()}
event["date"] = event["date"].isoformat()
with open("event.json", "w") as file:
   json.dump(event, file)

The fix is to manually convert the datetime object into a string before serialization. By calling .isoformat() on the object, you transform it into a standardized string format that JSON can handle. This simple preprocessing step prevents the TypeError because json.dump() now only sees basic types. Keep an eye out for this error when your data includes timestamps from databases or APIs.

Fixing incorrect file modes with json.dump()

Using the wrong file mode with open() is a common mistake that’ll stop your script in its tracks. If you try to write data with json.dump() to a file opened in read mode ("r"), Python will raise an error. See what happens in this example.

import json

user = {"name": "John", "age": 30}
with open("user.json", "r") as file:  
   json.dump(user, file)

The script attempts to write data with json.dump(), but the file is opened in read-only mode ("r"). This conflict between the write operation and the file's permissions causes an error. The corrected code below shows the fix.

import json

user = {"name": "John", "age": 30}
with open("user.json", "w") as file:  
   json.dump(user, file)

The fix is to change the file mode from read ("r") to write ("w"). The json.dump() function needs permission to write, which the "w" mode provides. This allows your script to create a new file or overwrite an existing one with fresh data. Always double check your file mode when writing data, as it's a common source of errors that can stop your program unexpectedly.

Handling special characters encoding in json.dump()

When your data contains special characters like “é” or “€”, json.dump() can trip you up. By default, it escapes non-ASCII characters, which can make your JSON file hard to read or even cause errors. See what happens in this example.

import json

message = {"text": "Café au lait costs €5"}
with open("message.json", "w") as file:
   json.dump(message, file)

The json.dump() function defaults to an ASCII-only output, converting characters like “é” and “€” into escape sequences. This happens because the code doesn't specify how to handle them. See the correct approach in the code below.

import json

message = {"text": "Café au lait costs €5"}
with open("message.json", "w", encoding="utf-8") as file:
   json.dump(message, file, ensure_ascii=False)

The fix involves two key arguments. You'll need to specify the file's encoding and adjust how json.dump() handles characters.

  • Open the file using encoding="utf-8" to support a wide range of characters.
  • Pass ensure_ascii=False to json.dump() to write special characters like “é” and “€” directly, rather than as escape codes.

This combination ensures your JSON file is both correct and human-readable, especially when dealing with international text or data from APIs.

Real-world applications

Now that you can sidestep common errors, you can use json.dump() for practical applications like managing configuration files and exporting data.

Storing application configuration settings with json.dump()

The json.dump() function is ideal for saving a dictionary of application settings to a configuration file, allowing your program to remember user preferences like a theme or font size.

import json

app_config = {
   "theme": "dark",
   "font_size": 12,
   "auto_save": True,
   "recent_files": []
}

with open("app_config.json", "w") as config_file:
   json.dump(app_config, config_file, indent=2)

This script serializes the app_config dictionary into a JSON file. The json.dump() function takes the dictionary and writes it directly to app_config.json in a structured format.

  • The with open() statement opens the file in write mode ("w"), which creates the file or overwrites it if it already exists.
  • Using indent=2 formats the output with two-space indentation, making the resulting JSON file easy for you to read.
  • This process automatically converts Python data types—strings, numbers, and lists—into their corresponding JSON equivalents.

Creating a simple data export tool with json.dump()

The json.dump() function is also great for creating simple data export tools that process information before writing it to a file for backups or reporting.

import json
from datetime import datetime

sales_data = [
   {"product": "Laptop", "units": 5, "price": 1200.00},
   {"product": "Monitor", "units": 10, "price": 300.00},
   {"product": "Keyboard", "units": 15, "price": 80.00}
]

# Calculate total sales for each product
for item in sales_data:
   item["total"] = item["units"] * item["price"]

filename = f"sales_export_{datetime.now().strftime('%Y%m%d')}.json"
with open(filename, "w") as export_file:
   json.dump({"sales": sales_data, "generated_at": datetime.now().isoformat()}, export_file, indent=2)

This script enriches the data before saving it. It first iterates through the sales_data list, calculating a new total for each product and adding it to the existing dictionaries. This shows how you can process data in-place before serialization.

  • A dynamic filename is created using strftime(), ensuring each day's export is unique.
  • The final output is a dictionary that wraps the sales list and includes a generated_at timestamp, which is converted to a string using isoformat().

Get started with Replit

Turn your knowledge of json.dump() into a real tool. Describe what you want to build to Replit Agent, like “a tool that saves user settings to a formatted JSON config file” or “a script that exports sales data with timestamps to JSON.”

The agent writes the code, tests for errors, and deploys your application right from your browser. Start building with Replit.

Get started free

Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.

Get started for free

Create & deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.