How to Open Large JSON Files Without Crashing Your Editor
Loading a 121 MB JSON file took over a gigabyte of memory in jq. Streaming the same file took 3 MB. Here is how to explore large JSON without loading it all at once.
Opening a large JSON file in an editor or a browser tab often freezes it. A JSON Tree Viewer in a browser tab is the most comfortable way to read a document, up to a point. Its page notes that documents beyond tens of megabytes run into browser memory. Database exports, log archives and analytics dumps are often far larger than that.
This guide works through one such file: an array of 600,000 orders, 121 MB on disk. Every time and memory figure comes from running the command on that file on one laptop. Your numbers will differ, but the ratios between the methods are what matter.
Measure and peek before opening anything
Two cheap commands tell you what you are dealing with, without parsing anything:
$ ls -lh orders.json | awk '{print $5}'
121M
$ head -c 160 orders.json
[{"id":"ord_0000000","status":"shipped","customer":{"id":"u_19773","country":"US"},"items":[{"sku":"SKU-50","qty":1,"price":164.79},{"sku":"SKU-97","qty":3,"priThe first characters show the shape: a top-level array of order objects, written without whitespace. That decides the approach. A top-level array can be streamed one element at a time; a single giant object with one huge key is harder.
What loading the whole file costs
Parsing the whole document turns compact text into objects, and objects take far more memory than their JSON text. Peak memory for one full parse of the 121 MB file:
jq length orders.json 8.0 s 1,277 MB
python3 json.load 5.1 s 927 MB
node JSON.parse(readFileSync(...)) 1.8 s 599 MBThat is 5 to 10 times the file size. Node also has a hard ceiling: it cannot create a string longer than about 512 MB, so readFileSync(path, "utf8") on a larger file fails with ERR_STRING_TOO_LONG before JSON.parse even starts. An editor or browser tab that renders the parsed tree needs memory on top of all this.
Stream a large JSON file with jq
jq's --stream mode reads the document as a sequence of small events instead of building the whole tree. Combined with fromstream it hands you one array element at a time. To see the first three orders:
jq -cn --stream 'limit(3; fromstream(1|truncate_stream(inputs)))' orders.jsonThat returned in 0.01 seconds using 3 MB, because jq stops reading as soon as it has three elements. The expression looks cryptic, but it is a fixed recipe: 1|truncate_stream(inputs) removes the outer array level, and fromstream rebuilds each element.
Convert to one record per line
For repeated exploration, convert the array into newline-delimited JSON, one order per line. Every line-based tool then works on it. There are two ways, with opposite costs:
jq -cn --stream 'fromstream(1|truncate_stream(inputs))' orders.json > orders.ndjson
76 s 3 MB
jq -c '.[]' orders.json > orders.ndjson 16 s 1,269 MBBoth produce identical output. Use the fast one when the machine has memory to spare, and the streaming one when it does not, for example inside a small container. After the conversion, everything is quick and light:
# Count matching records: 2.1 s, 1 MB
grep -c '"status":"refunded"' orders.ndjson
# Filter on several fields, line by line: 4.4 s, 3 MB
jq -c 'select(.status == "refunded" and .customer.country == "IN") | .id' orders.ndjson
# Split into files of 100,000 records each: 2.6 s
split -l 100000 orders.ndjson part-A grep count is only safe when the text you search for cannot appear inside other fields. Here status occurs once per order, so it counts orders. When in doubt, use the jq version. Each split file holds 100,000 complete records, small enough for the tree viewer or an editor.
Read a large JSON file in Python
When the exploration turns into a script, use a streaming parser rather than json.load. In Python, ijson yields one array element at a time:
import ijson
with open("orders.json", "rb") as f:
refunded = sum(1 for order in ijson.items(f, "item") if order["status"] == "refunded")On the same file that took 4.6 seconds and 18 MB, against 927 MB for json.load. The prefix "item" means each element of the top-level array; for a nested array, use a path such as "data.orders.item".
When a browser tab is enough
Use the tree viewer for documents up to a few tens of megabytes, and for any slice you have extracted from a bigger file: one record, one split file, or the output of a jq filter. The terminal is for finding the part worth looking at; the tree view is for reading it.
Related tools
Pretty-print JSON with configurable indentation and instant validation.
Query JSON with JSONPath expressions and see live results.
Analyze JSON size, depth, key counts, and type distribution.
Flatten nested JSON into single-level dot-notation key paths.
Related guides
Two formatters can disagree about the same JSON file. Here is how a team picks one, applies it in every editor and before every commit, and makes CI enforce it.
Three query languages for JSON look alike and behave differently. Here are ten everyday queries in all three, with the results they actually return.
A payload can be 19,847 characters, 20,197 bytes and 1,803 bytes on the wire, all at once. Here is which number an API limit, a database or a browser actually checks.
A recursive function of about ten lines flattens any JSON document into path keys. Here it is for JavaScript and Python, with the choices that decide whether you can rebuild the original.