Mateen Kiani
Published on Wed Jul 16 2025·9 min read
Working with JSON is a daily part of many Python projects. We use JSON for config files, API payloads, and data exchange. But one often overlooked aspect is handling Unicode characters and ensuring proper encoding when writing to a file. Forget this and you might end up with escaped characters or broken text. How can you make sure your JSON file stays readable and correctly encoded?
You can use Python’s built-in json
module with the ensure_ascii
parameter set to False
and open the file with the right encoding. This combination ensures Unicode characters are written as is, not escaped. Understanding this lets you maintain readability and data integrity for international text. It also prevents surprises when your application reads the file later.
JSON is more than just a data-interchange format. It powers configuration files, API responses, and logs across dozens of Python libraries. You will find JSON in web applications, data processing scripts, and even microservices. Knowing how to write JSON files helps you standardize outputs. It keeps data structured and portable.
Here are common scenarios where writing JSON to a file adds value:
By storing JSON on disk, you can inspect files directly. Version control tools will also show changes clearly. This transparency helps during debugging. As your projects grow in complexity, writing clear JSON files becomes a cornerstone of maintainable code.
Whenever you write a JSON file, choose a clear name and use the .json
extension. This ensures your editor applies the right syntax highlighting. You can open the file in any text editor to verify its contents. Many CI/CD pipelines automatically validate JSON files before deploying. If the file is malformed, automated checks can fail early and save you from runtime errors in production.
For cross-language projects, JSON acts as a neutral format. A file written in Python can be consumed by JavaScript, Java, Go, or any language with a JSON parser. This flexibility makes JSON the go-to format for data interchange. Understanding why JSON files matter sets the stage for learning how to write them correctly in Python.
Writing JSON in Python is straightforward thanks to the built-in json
module. Start by importing the module and preparing your data. Here is a minimal example:
import jsondata = {"name": "Alice","age": 30,"languages": ["Python", "JavaScript", "Go"]}with open("user.json", "w", encoding="utf-8") as file:json.dump(data, file)
In this snippet:
json
.user.json
in write mode.json.dump()
.Note that json.dump()
writes the JSON text directly to the file. If you need a string instead, use json.dumps()
. Dumping directly is more efficient because it does not build a large in-memory string.
Tip: Add a newline at the end of the file for better command-line display:
python
with open("user.json", "w", encoding="utf-8") as file:
json.dump(data, file)
file.write("\n")
When you open the file in write mode ("w"
), Python creates the file if it does not exist. If the file exists, it is overwritten. To append JSON objects, use append mode ("a"
) but be cautious: you will need to manage commas and array brackets manually. For most use cases, writing a complete JSON structure in one shot is simpler.
Remember that file paths can be relative or absolute. If you point to a nested directory, ensure the directory exists first. Use os.makedirs()
with exist_ok=True
to create folders automatically:
import osos.makedirs("data", exist_ok=True)with open("data/user.json", "w", encoding="utf-8") as file:json.dump(data, file)
Handling paths and modes correctly prevents runtime errors and makes your scripts more reliable. Up next, learn how to format JSON for humans.
By default, json.dump
writes everything in one long line. That is efficient but hard to read by humans. You can improve readability with the indent
parameter. This adds line breaks and spaces. Here is how:
with open("user.json", "w", encoding="utf-8") as file:json.dump(data, file, indent=4)
Common formatting options:
','
, ':'
).True
to sort dictionary keys alphabetically.False
to allow Unicode characters without escaping.Example with all options:
json.dump(data,file,indent=2,separators=(',', ': '),sort_keys=True,ensure_ascii=False)
Tip: Use
ensure_ascii=False
to prevent Unicode characters from being written as escape sequences like"\\u2013"
. This makes the JSON file easier to read and edit manually.
Readable JSON is easier to validate with linters and diff tools. It also makes debugging faster, especially when teams collaborate on configuration files or API samples.
You can further customize formatting by writing a custom JSONEncoder
or post-processing with .replace()
for special formatting needs. But for most cases, indent
and separators
cover the essentials. Next, we will show how to handle complex data types.
Standard JSON types include strings, numbers, arrays, and objects. But real-world data often includes types like datetime
, Decimal
, or custom classes. json.dump
will fail on these by default. You need to convert or encode them manually. There are two main strategies:
json.JSONEncoder
to handle special types.Example using preprocessing:
from datetime import datetimerecord = {"user": "Bob","timestamp": datetime.utcnow()}# Convert datetime to ISO stringrecord["timestamp"] = record["timestamp"].isoformat()with open("record.json", "w", encoding="utf-8") as f:json.dump(record, f, indent=2, ensure_ascii=False)
Example using a custom encoder:
import jsonfrom datetime import datetimeclass MyEncoder(json.JSONEncoder):def default(self, obj):if isinstance(obj, datetime):return obj.isoformat()return super().default(obj)data = {"time": datetime.now()}with open("data.json", "w", encoding="utf-8") as f:json.dump(data, f, cls=MyEncoder)
This approach keeps your serialization logic in one place and scales better for multiple special types. If you plan to serve JSON data over HTTP, take a look at this REST API with Flask guide. By customizing the encoder, you ensure consistent output across your application.
When writing JSON files, you may encounter two main errors: I/O errors and serialization errors. Proper error handling prevents crashes and data loss. Here is a pattern to follow:
import jsonfrom json import JSONDecodeErrortry:with open("config.json", "w", encoding="utf-8") as file:json.dump(config_data, file, indent=2)except JSONDecodeError as jde:print("Serialization error:", jde)except OSError as ose:print("File write error:", ose)
Tip: Catch
JSONDecodeError
when usingjson.loads
orjson.dump
. It helps you identify malformed data before it goes to disk.
For large data, you might want to write in chunks. In that case, wrap json.dumps
calls:
def write_chunked(data_list, filepath):try:with open(filepath, "w", encoding="utf-8") as f:f.write("[\n")for item in data_list:chunk = json.dumps(item, ensure_ascii=False, indent=2)f.write(chunk + ",\n")f.write("]\n")except Exception as e:print("Error writing chunked JSON:", e)
Using with
ensures the file is closed even if an error occurs. Always validate your data shapes before dumping to avoid unexpected exceptions.
Writing JSON files fast and safely matters when dealing with large datasets. Here are some tips to optimize performance:
json.dump
over json.dumps
to avoid large intermediate strings.Example of streaming:
def stream_json(data_iter, filepath):with open(filepath, "w", encoding="utf-8") as f:f.write("[")first = Truefor item in data_iter:if not first:f.write(",")f.write(json.dumps(item))first = Falsef.write("]")
Data integrity is also key. Always write to a temp file first and rename on success:
import osimport jsontemp_path = filepath + ".tmp"with open(temp_path, "w", encoding="utf-8") as f:json.dump(data, f)os.replace(temp_path, filepath)
This approach prevents corrupt files if the process is interrupted. Finally, track your JSON files in version control. For an introduction to Git and GitHub, check this guide to Git and GitHub.
Writing JSON to a file in Python is simple at first glance, but mastering it opens up safe data storage, readable configurations, and reliable APIs. We covered the basics with json.dump
, improved readability using indent
and separators
, handled complex data via custom encoders, and implemented error strategies to prevent crashes. Along the way, we learned how to optimize for performance with streaming writes and atomic file replaces. By following these practices, you ensure your JSON files are robust, maintainable, and ready for collaboration.
Next time you need to dump data in Python, use these patterns to avoid common pitfalls. Whether you are developing a small script or a large application, proper JSON writing can save hours of debugging. Dive into the code examples, adapt them to your needs, and consider exploring more on REST API with Flask when building web services. Now you’re equipped to write JSON files like a pro—go ahead and give it a try!
Use Python's json module—open file with open('file.json','w', encoding='utf-8') and call json.dump(data, file, indent=4, ensure_ascii=False).