Read, Validate, and Export JSON with Python
Use Python's standard library for repeatable local JSON jobs, preserve identifiers, and write a deliberate CSV column mapping.
By JSON Lab · Updated
Use a local script when a transformation repeats, the data should stay in a controlled environment, or an interactive browser tool is too small for the task. Start with Python's standard library and add dependencies only for a requirement it cannot meet.
Read and write a small JSON file
Save this as input.json:
{"id":"001","name":"Ana","active":true}
Then run:
import json
with open("input.json", encoding="utf-8") as source:
record = json.load(source)
if not isinstance(record, dict):
raise ValueError("Expected one object")
with open("formatted.json", "w", encoding="utf-8") as target:
json.dump(record, target, ensure_ascii=False, indent=2, allow_nan=False)
target.write("\n")
print(record["id"])
The printed ID is 001. The output file contains the same record with indentation. The script writes a separate file so you can compare it with the original before replacing anything.
Report malformed input clearly
Wrap parsing at the boundary where you can display a useful error:
import json
try:
json.loads('{"quantity": 2,}')
except json.JSONDecodeError as error:
print(f"Invalid JSON at line {error.lineno}, column {error.colno}")
The example reports a syntax error. Do not catch it and silently continue with an empty object; an empty result can look like a successful import.
Preserve important numeric values
Python integers can represent values larger than JavaScript's safe integer range, but another system receiving the JSON may not. Use strings for identifiers shared with browser applications.
For decimal calculations, you can request Decimal when loading fractional numbers:
import json
from decimal import Decimal
record = json.loads('{"amount": 0.1}', parse_float=Decimal)
assert record["amount"] == Decimal("0.1")
The standard encoder does not automatically serialize Decimal. Choose an explicit output contract, such as a decimal string or integer minor units, rather than converting back to float and assuming exactness.
Export a known record shape to CSV
For a trusted sample with a fixed schema:
import csv
records = [
{"id":"001","address":{"city":"Paris"}},
{"id":"002","address":{"city":"Rome"}},
]
with open("records.csv", "w", encoding="utf-8-sig", newline="") as target:
writer = csv.DictWriter(target, fieldnames=["id", "address.city"])
writer.writeheader()
for record in records:
writer.writerow({
"id": record["id"],
"address.city": record.get("address", {}).get("city", "")
})
The output has columns id and address.city, followed by the two records. The explicit mapping is useful: it states exactly which fields an export contains.
This small script is not a general nested-object converter and does not add spreadsheet formula protection. For an interactive preview, adjustable columns, and that protection, use JSON to CSV. For untrusted production exports, implement and test the corresponding destination policy in your script.
Do not mistake file I/O for streaming parsing
Calling json.load reads a complete JSON value into Python objects. If the file is too large, changing the file handle's buffer size does not make that parse incremental.
Use JSON Lines for independent records when the producer supports it, or an incremental parser for a large existing array. Measure your actual workload using the performance checklist before choosing a different parser.