Flattening Nested JSON to Dot Notation (and Getting It Back)

Flattening turns a tree into a table. Useful for CSV, environment variables and feature flags — with one edge case that silently corrupts data.

Flattening Nested JSON to Dot Notation (and Getting It Back)
Share this article:

Plenty of systems only accept flat key-value data. Environment variables, CSV columns, most feature-flag services, form encoding, analytics event properties. Nested JSON does not fit any of them.

Flattening solves that by encoding the path into the key:

{ "user": { "name": "Ada", "address": { "city": "London" } } }

becomes

{ "user.name": "Ada", "user.address.city": "London" }

Nothing is lost. The structure moved from the shape of the document into the text of the keys.

The syntax

Two rules cover everything:

  • A dot separates object levels. `user.address.city` walks down three levels.
  • Brackets mark array positions. `tags[0]` is the first element, `posts[2].title` the title of the third post.
NestedFlattened
`{"a": {"b": 1}}``{"a.b": 1}`
`{"tags": ["x", "y"]}``{"tags[0]": "x", "tags[1]": "y"}`
`{"a": {"b": {"c": 2}}}``{"a.b.c": 2}`
`{"list": [{"id": 1}]}``{"list[0].id": 1}`
`{"empty": {}}``{"empty": {}}`

That last row matters more than it looks. An empty object or array has no leaves to walk to, so a naive flattener drops it entirely and the round trip loses data. Preserving it as a leaf is what makes flatten-then-unflatten exact.

The JSON flattener does both directions, so you can verify a round trip in a few seconds.

When you actually need it

Nested JSON to CSV. A spreadsheet has columns, not trees. Flattening gives you one column per leaf — `user.name`, `user.address.city` — which is exactly what a CSV needs. Flatten first, then use the CSV and JSON converter.

Configuration into environment variables. Env vars are flat strings. A nested config flattens to `DATABASE.HOST` style keys that map onto `DATABASE_HOST` with a separator swap. The ENV to JSON converter handles the dotenv side.

Feature flags and analytics. Most providers accept flat attributes only. Flattening lets you send a nested user object without restructuring your application code.

Diffing config files. A flat document diffs cleanly line by line, because each line is a complete path and value. Nested documents produce diffs where an indentation change looks like a content change.

The case where it breaks

Flattening is lossy when your keys already contain the separator.

{ "example.com": { "ttl": 300 } }

flattens to `{"example.com.ttl": 300}`. Unflattening that produces:

{ "example": { "com": { "ttl": 300 } } }

Three levels where you had two. The original key is unrecoverable, because there is nothing in the flat form distinguishing a literal dot from a structural one.

This is not exotic. Keys containing dots turn up constantly — domain names, file paths, version numbers, IP addresses, package names. If your data has any of them, flattening will corrupt it silently, which is the worst kind of corruption.

The honest answer is that dot-notation flattening is unsuitable for that data, and you should restructure it rather than look for an escape mechanism.

Common mistakes

  • Expecting it to reduce size. It usually increases it — every leaf now carries its full path. Flattening is for compatibility, not compression.
  • Storing data flat long-term. Once flat you cannot query a subtree without string-prefix matching, which is slower and more fragile than working with the nested form.
  • Ignoring sparse arrays. A flat document with `items[0]` and `items[2]` but no `items[1]` unflattens to an array with a hole. Check the length before trusting it.
  • Hitting key-length limits. Deep nesting produces long keys, and some databases cap field-name length.
  • Assuming key order is preserved. Most engines keep insertion order in practice, but the JSON specification does not require it.

Frequently asked questions

Is flattening reversible?

Yes, unless your keys contain dots or brackets. Flatten then unflatten and compare against the original — the [JSON diff tool](/compare-json) makes that check quick.

What happens to null?

It is a leaf value like any other and survives the round trip unchanged.

Can I use a different separator?

Not in this tool. Other libraries allow it, which helps if your keys contain dots but not, say, colons.

Does it handle very deep nesting?

Yes, though the keys get unwieldy. Beyond five or six levels, flattening usually indicates the data model needs rethinking rather than converting.

How does this differ from JSON Path?

JSON Path is a query language for selecting parts of a document. Flattening rewrites the whole document. The path syntax looks similar, which causes confusion.

Related reading

For getting flattened records into a spreadsheet, the CSV and JSON converter is the next step. If the goal is environment variables, the ENV to JSON converter handles dotenv syntax. To confirm a round trip was lossless, the JSON diff tool compares structurally.

Flatten some JSON →