Flatten JSON
Turn nested JSON into one flat level of dot or bracket key paths — or rebuild the nested document from those paths. Custom separators, ENV/SQL key casing, and JSON, key=value, CSV or key-list output. Runs entirely in your browser, no server, no sign-up.
About this tool
Flatten JSON collapses a nested JSON document into a single level of
path → value pairs, so {"user":{"name":"Ada"}} becomes {"user.name":"Ada"}.
It also runs the other way: point it at a flat map of paths and it rebuilds the
nested document. Both directions are lossless, so you can flatten, edit or diff
the flat form, and unflatten it back. Everything runs locally in your browser —
your JSON is never uploaded.
Paths use the familiar lodash / dot-object / flat style, not RFC 9535
JSONPath:
- Object keys are joined by the separator —
.by default (user.address.city), but_or/or any 1–8 characters work. - Array elements use the array index notation —
bracket(default) writestags[0],separatorwritestags.0.
Worked example
Given this document:
{"user":{"name":"Ada","tags":["admin","beta"]},"active":true}
flattening with the defaults gives:
{
"user.name": "Ada",
"user.tags[0]": "admin",
"user.tags[1]": "beta",
"active": true
}
Paste that result back in with direction = unflatten and you get the original nested document, byte for byte — key order is preserved, not alphabetised.
Change the output format to get the same data in a different shape. With
separator = _, key case = upper and output = pairs, the document
{"db":{"host":"localhost","port":5432},"debug":false} becomes an env-file:
DB_HOST=localhost
DB_PORT=5432
DEBUG=false
and output = csv gives a two-column sheet you can paste straight into a
spreadsheet:
key,value
order.id,A-17
order.items[0].sku,X1
order.items[0].qty,2
output = paths prints just the path list — handy for auditing which fields an
API actually returns.
Options worth knowing
- Direction —
flatten(default),unflatten, orauto.autounflattens only when the input is a one-level object whose keys already look like paths, and flattens otherwise. - Max depth —
0(default) flattens everything. With2,{"a":{"b":{"c":1}}}becomes{"a.b":{"c":1}}and anything deeper stays as a nested JSON value. - Expand arrays — turn it off to keep every array whole as one JSON value while still flattening objects, which is what you want when a list is a single logical cell.
- Keep empty objects and arrays — on by default, so
{}and[]survive as leaf entries and round-trip. Turn it off to drop those keys. - Key case —
uppergives ENV-style keys,lowergives SQL-style column keys,preserve(default) keeps the source spelling.
Limits & edge cases
- Key collisions are an error, not a silent merge. If a source key already
contains the separator, two different paths can flatten to the same key — the
run fails and names the key so you can pick another separator. The same applies
when
upper/lowercasing merges two keys that differed only in case. - Unflatten refuses conflicting paths. Supplying both
aanda.berrors instead of overwriting whichever came second. - Bracket vs dotted indices change the round-trip. With
separatornotation an all-digit segment rebuilds an array; withbracketnotation it stays an object key literally named"0". Use the same setting in both directions. - Upper/lower key case is lossy — the original key spelling can't be recovered by unflattening.
- Non-JSON output formats are flatten-only. Unflattening always returns
nested JSON, so
pairs/csv/pathserror rather than being ignored. - Input is capped at 5 MB, 100 levels of nesting, 200,000 flattened
keys, and array indices up to 100,000 (so a typo like
a[999999999]errors instead of allocating a huge array). - A top-level array flattens too:
[{"a":1}]gives{"[0].a":1}.
FAQ
What's the difference between bracket and dotted array indices?
bracket writes tags[0], separator writes tags.0 using whatever separator
you chose. Bracket is the default because it is unambiguous: [0] can only mean
an array element, so a bare numeric segment is free to mean an object key
literally named "0". With separator notation the rule flips — an all-digit
segment rebuilds an array. Both round-trip cleanly as long as you flatten and
unflatten with the same setting.
Can I get the nested JSON back after flattening?
Yes — that's what direction = unflatten does. Paste the flat map of paths back
in and the nested document is rebuilt, with key order preserved. The round-trip
is lossless for every option except key case = upper/lower (which discards
the original spelling) and a max depth cap combined with dropping empty
containers.
Why did I get a "two different paths flatten to the same key" error?
Because a key in your document already contains the separator. For example
{"a.b":1,"a":{"b":2}} produces the path a.b twice — one from the literal key,
one from the nested object. Rather than silently dropping a value, the tool stops
and names the key. Pick a separator that doesn't appear in your keys (/, ::
and __ are common choices).
How do I turn a nested API response into a spreadsheet?
Set output to csv. You get a two-column key,value sheet with a header
row, correctly quoted for values containing commas, quotes or newlines — paste it
straight into a spreadsheet. If you'd rather have an env file or a .properties
style dump, use pairs, which prints path=value lines with strings unquoted.
What happens to empty objects, arrays, and nulls?
null is an ordinary value and always survives as a leaf. Empty objects and
arrays have nothing inside to make a path from, so they're controlled by keep
empty objects and arrays: on (the default) they're emitted as {} / [] leaf
entries so the key survives the round-trip; off, those keys are dropped entirely.
Is my JSON uploaded anywhere?
No. The whole tool is compiled to WebAssembly and runs inside your browser tab, so the document never leaves your device. That makes it safe for config files, API responses, and anything else you wouldn't paste into a server-side converter.
Developer & Automation Access
Run it from the terminal
Same engine as this page, headless — via the gizza CLI:
gizza tool flatten-json '{"user":{"name":"Ada","tags":["admin","beta"]},"active":true}'New to the CLI? Get gizza →
Open it by URL
Pre-fill and auto-run this tool with query parameters — the names match the API/CLI:
https://gizza.ai/tools/flatten-json/?json=%7B%22user%22%3A%7B%22name%22%3A%22Ada%22%2C%22tags%22%3A%5B%22admin%22%2C%22beta%22%5D%7D%2C%22active%22%3Atrue%7D&direction=flatten&separator=.&array_notation=bracket&max_depth=0&flatten_arrays=true&preserve_empty=true&key_case=preserve&output=json&pretty=true&indent=2Machine-readable descriptor: tool.json — title + parameters JSON Schema for agents.
