JSON Flatten

Nested JSON goes in, one line per leaf comes out. Choose dot notation for pandas and most config systems, slash notation for JSON Pointer, or bracket notation for JavaScript and jq. Take the result as a path listing, as a flattened JSON object keyed by path, or as a CSV with a type column. There is no depth limit.

Try an example loads a nested order document with an array of line items in it.

Three notations, because three tools want three things

The path style is not cosmetic. Whichever tool you are heading towards expects one particular spelling, and handing it another means editing every line.

StyleLooks likeWanted by
Dotlines.0.skupandas json_normalize, Spring properties, most config systems, dbt
Slash/lines/0/skuJSON Pointer, JSON Patch, OpenAPI, Kubernetes strategic merge
Bracket["lines"][0]["sku"]JavaScript, jq, and anything you are about to paste into code

Each style handles awkward keys correctly rather than producing something that looks right and does not parse. A key containing a dot cannot use dot notation, so it falls back to a bracketed quoted form: user["first.name"]. A key containing a slash cannot use slash notation, so JSON Pointer's escaping applies and it becomes ~1, with ~ itself becoming ~0.

Array indexes follow the style too: lines.0 in dot notation, /lines/0 in slash, [0] in bracket.

Worked example: an order document

This is the sample:

{
  "order_id": "A-1043",
  "placed_at": "2026-09-03T10:14:00Z",
  "customer": { "name": "Ada Lovelace", "email": "ada@example.com", "vip": true },
  "lines": [
    { "sku": "W-1", "qty": 2, "price": 19.99 },
    { "sku": "G-7", "qty": 1, "price": 240 }
  ],
  "discount": null,
  "notes": ""
}

In dot notation, as a path listing:

order_id = A-1043
placed_at = 2026-09-03T10:14:00Z
customer.name = Ada Lovelace
customer.email = ada@example.com
customer.vip = true
lines.0.sku = W-1
lines.0.qty = 2
lines.0.price = 19.99
lines.1.sku = G-7
lines.1.qty = 1
lines.1.price = 240
discount = null
notes = 

Thirteen paths, deepest is three levels. Both empty-ish values are there: discount is null and notes is an empty string. Dropping them would lose the fact that the keys exist, which is exactly what somebody diffing two payloads is looking for.

Switch the output to CSV and you get three columns, path, value and type, which is the form you want when the next step is a spreadsheet or a comparison. Switch it to Flattened JSON and you get an object whose keys are the paths, which is what a feature store or a flat config system expects.

No depth cap, and why that is a choice

There is a second flattener on this site, the one behind JSON to CSV, and it stops at four levels. That is deliberate there: it is building a rectangle, and a spreadsheet column called a.b.c.d.e.f.g helps nobody, so anything deeper is kept as JSON text in a single cell.

Here the path is the deliverable rather than a column name, so it goes all the way down. A twelve-level Kubernetes manifest produces twelve-segment paths, and that is the correct answer to the question this page is being asked.

Empty objects and empty arrays are leaves

An empty container has no leaves under it, so a naive walk produces no line for it at all and the key disappears from the output. This one emits the container itself as a leaf:

config.retries = 3
config.hooks = []
config.labels = {}

That matters whenever the flattened form is being compared against another one. "The key is present and empty" and "the key is absent" are different states, and they are different for a reason: one is a configured empty list, the other is a field somebody forgot.

What people do with the result

  • Diffing two API payloads. Flatten both, sort, and a text diff shows exactly which leaves changed. Structural diffs of nested JSON are hard to read; diffs of sorted path listings are trivial.
  • Building a data dictionary. The CSV output has a type column, so a document becomes a list of every field with its type in one step.
  • Feeding a flat config system. Spring, Consul and a dozen others take dotted keys. Flattened JSON output is the exact shape they read.
  • Writing a JSON Patch. Slash notation is JSON Pointer, so the paths are usable in a patch document without editing.
  • Finding what is in a document you were given. Sometimes the honest answer is that you just want to see every field, and thirteen lines beats scrolling a nested structure.

The tolerant reader is wired in here too, so a config file with comments or a Python dict flattens without complaint, with a note saying what was forgiven.

Frequently Asked Questions

How is the separator in the listing changed?

The "Separator in the listing" box. It defaults to = and takes any text, so : , \t typed as a tab, or an arrow all work. It only affects the listing output; the CSV and the flattened JSON have their own structure.

Which output should I pick?

Path listing if you are reading it or diffing it. CSV if the next step is a spreadsheet or you want the type column. Flattened JSON if a program is going to consume it, particularly a config system that reads dotted keys.

Does it explode an array of objects into rows?

No, and that is a different operation. Here each array element gets its own indexed path, so lines.0.sku and lines.1.sku are two separate leaves. If you want one row per array element in a table, that is what JSON to CSV does.

What happens to a key with a dot in its name?

In dot notation it is bracketed and quoted, so {"user":{"first.name":"Ada"}} becomes user["first.name"] rather than an ambiguous user.first.name. In slash notation the JSON Pointer rules apply and a slash in a key becomes ~1.

Is there a limit on the nesting depth?

No. The path is the output here, so there is nothing to cap. The related JSON to CSV converter does cap at four levels, because it is building spreadsheet columns and a seven-segment column name is unusable.

Can it read a file that is not strict JSON?

Yes, with "Forgive non-strict JSON" left on. Comments, trailing commas, single quotes, unquoted keys and Python True/False/None are all read, and a note above the result says what had to be forgiven.

Does anything I paste leave my computer?

No. There is no upload endpoint on this page and no network request in the code that does the work. JavaScript in your own tab reads the text, processes it and hands back the result. Nothing is stored between visits either, so reloading gives you an empty box again. You can confirm it by opening your browser's network panel and watching it stay quiet while you work.

One line per leaf

Free, no account, no upload. Three notations, three output shapes, no depth limit.

Back to the flattener