An API response comes back at 2,000 lines. The field you need is in there, four levels down, inside an array of objects that each hold another array. The documentation says so. Finding the exact path by eye is not reading, it is counting braces.
I do this most weeks, usually with a response from a supplier's system or a JSON blob copied out of a log. This post covers the JSONPath syntax that names a location so you can stop counting, the order in which I look when I do not know where a field is, and the jq one-liners that replaced most of the small scripts I used to write for this.
JSONPath in six symbols
JSONPath does for JSON what XPath does for XML: it describes where a value lives, so you can ask for it instead of walking to it. It was a convention for fifteen years, with small differences between libraries. Since 2024 it is an IETF standard, RFC 9535, and the newer libraries follow it.
The whole language fits in six symbols:
$is the root. Every path starts there..namesteps into a property.$.storeis the store object at the root.[0]picks an array element.[-1]is the last one.matches everything at that level.$.store.book[].authoris every author...searches all descendants.$..pricefinds every price at any depth.[?expr]filters.$.store.book[?@.price < 10]is the books under ten.
Older libraries write the filter as [?(@.price < 10)], with parentheses. RFC 9535 drops them, and most implementations accept both forms.
Libraries: jsonpath-plus for JavaScript, jsonpath-ng for Python, Jayway JsonPath for Java. One warning about the JavaScript one. Versions of jsonpath-plus before 10.0.7 evaluated filter expressions in a way that allowed code execution, and it took two CVEs, in 2024 and 2025, to close the hole. Update it, and never let user input into a filter expression in any library.
If you want the path to a value without installing anything, the JSON Path Finder shows the document as a tree in the browser. Click the value, and the path is there to copy.

How I find a field when I do not know the path
The syntax is the easy part. Sitting in front of a 50 KB response, knowing the value is in there somewhere, is the hard part. This is what I do, in this order.
Format it. Minified JSON on one line is not readable by anyone. The JSON Formatter indents it and, more usefully, says on the spot when it does not parse, with the line and character. Half the time the field I could not find was on the far side of a syntax error.
Search for a value you know. An ID, a name, a status string. Find the value, then walk up the indentation to build the path. This is faster than reading down from the top, every time.
Collapse to the skeleton. The JSON Tree Viewer shows the document folded, so you see the top-level keys first and open one branch at a time. Two or three levels in, the shape of the thing is usually obvious.
Ask the console. In the browser or a Node REPL:
`javascript
const data = JSON.parse(rawJson);
Object.keys(data); // top-level keys
Object.keys(data.results[0]); // keys of the first result
`
Once I have the path, that is what goes in the defect report, not a description of where to look. A path is a fact. "The status field in the second block" is an argument waiting to happen.
The syntax is the easy part.
Flatten it when a table is what you need
Sometimes the right answer to nested JSON is to stop it being nested. A flat table is easier to scan, filter and sort, and it is what the people you send it to can open.
The JSON to CSV converter flattens a document into rows. The CSV to JSON converter builds nesting back up when a spreadsheet has to become an API request. There are three ways to flatten, and you should pick one on purpose.
Dot-notation keys. {"user": {"name": {"first": "Jane"}}} becomes a column called user.name.first. The hierarchy survives in the header. This is the default I want for anything going to Excel.
Unwinding arrays. A parent with three children becomes three rows with the parent fields repeated. MongoDB calls this $unwind. It is what a relational database wants, and it multiplies your row count, so count before and after.
Selective extraction. Do not flatten the document at all. Pull the five fields you need with JSONPath and leave the rest. This is the one that scales, and it is what $.. is for.
Arrays of uneven length are where flattening goes wrong. CSV rows want the same number of columns, and a record with two phone numbers next to one with five forces you to pad or to unwind. Decide before you convert, not after the columns have shifted.

jq replaces most of the scripts
For anything in a terminal, jq is the tool. It filters and restructures JSON from a file or straight out of curl, and its syntax is close enough to JSONPath that one carries over to the other.
`bash
# Pretty-print
jq '.' data.json
# One field jq '.results[0].name' data.json
# Every name in an array jq '.results[].name' data.json
# Filter jq '[.results[] | select(.status == "active")]' data.json
# Restructure jq '.results[] | {id: .id, fullName: (.first + " " + .last)}' data.json
# Count
jq '.results | length' data.json
`
Straight from an API:
`bash
curl -s https://api.example.com/users | jq -r '.data[] | select(.role == "admin") | .email'
`
Fetch, filter to admins, print the emails one per line thanks to -r. No temp file, no script.
One correction to a claim you will read elsewhere: jq does not stream by default. It reads each input document into memory before it does anything. For a file that does not fit, use jq --stream, or a streaming parser in your language.
In Python the standard json module plus a comprehension does the same job:
`python
import json
with open('data.json') as f: data = json.load(f)
emails = [u['email'] for u in data['users'] if u['status'] == 'active']
`
For anything in a terminal, `jq` is the tool.
Six JSON mistakes that cost the most time
These come up so often that knowing them in advance is worth more than any tool.
Trailing commas. {"a": 1, "b": 2,} is valid JavaScript and invalid JSON. Anyone who writes JSON by hand after a day in JavaScript does this.
Single quotes. Strings take double quotes, no exceptions. {'name': 'Jane'} will not parse.
Comments. JSON has none. Not //, not / /, not #. If a config file needs comments, use JSONC (VS Code settings and tsconfig.json use it) or YAML, and do not call the file .json.
Big integers. JavaScript's Number loses precision above 2^53. An ID of 9007199254740993 comes out of JSON.parse as 9007199254740992, and nothing warns you. It is a nasty one to find because the number still looks plausible. Send large IDs as strings, or parse with BigInt.
Encoding. The standard says UTF-8 when JSON moves between systems. A Latin-1 export with an é in a surname gives you either a parse error or a garbled character, depending on which is worse for your day. Keep the whole pipeline UTF-8.
Nulls on the path. data.user.address.city throws when address is null. Use optional chaining, data?.user?.address?.city, or the null-safe equivalent in your language, and decide up front what a missing city should mean.
The JSON Formatter catches the first three the moment you paste. For the shape of the data rather than the syntax, write a JSON Schema and run samples through the JSON Schema Validator.
FAQ
Is there a maximum nesting depth in JSON?
The standard sets none. Parsers do: JSON.parse in JavaScript copes with hundreds of levels, streaming parsers with more. If your own data is more than five or six levels deep, the problem is the design, not the parser.
Does JavaScript support JSONPath natively?
No. Plain property access, data.results[0].name, covers most cases. You need a library such as jsonpath-plus only for wildcards, recursive descent or filters.
How do I open a JSON file that is too big for my editor?
Do not open it. Stream it. stream-json in Node, ijson in Python, jq --stream on the command line. Each reads the file piece by piece instead of loading it whole.
Can I flatten nested JSON to CSV without losing anything?
You can keep every value, but not every relationship. The hierarchy has to move into the column names or into repeated rows, and arrays of different lengths force a choice between padding and unwinding. If the structure matters more than the table, keep the JSON and query it instead.
### Is there a maximum nesting depth in JSON.
Environment Variables and .env Files: The Variable That Still Points at Production
How a .env file is meant to work, which file goes in git and which never does, the per-environment layout that keeps a test environment away from production, how each framework exposes variables to the browser, and what to do the day a .env file lands in the repository.
CSS Timing Functions: Ease-Out for Nearly Everything, and Keep It Short
Two animations can move the same element the same distance in the same time and only one feels right; the curve is the difference. The five keywords and when each applies, cubic-bezier values worth copying, durations that do not make people wait, the properties that stutter, and what linear() adds.
How to Convert Between JSON and CSV: A Developer's Guide
Learn when and how to convert between JSON and CSV formats. Practical examples for data migration, API responses, spreadsheet imports, and database exports.
JSON Guide: Format, Validate, and Convert JSON Files
JSON guide for developers: syntax rules, common parse errors, formatting and schema validation, plus how to convert between JSON and CSV files.
