JF

JSON Flatten / Unflatten

Flatten and restore JSON with typed object and array paths

JSON & Data
🔒 100% client-side — your data never leaves this page
Maintained by Evan•Updated: September 30, 2026

Typed paths such as $["object key"][0] distinguish object members from array indexes and preserve empty keys, special keys, root scalars and empty containers. $ identifies the root. Unflatten accepts scalar or empty-container leaves; conflicting paths and sparse arrays are errors. Legacy delimiters support a limited subset.

Strict JSON: duplicate keys and numeric changes are rejected. Integers must be within ±9007199254740991; decimals must round-trip to the same decimal value. Negative zero is unsupported. Input ≤2 MiB, depth ≤128, values ≤100000, output ≤8 MiB; paths ≤8192 characters, query results ≤10000, array indexes 0–99999.

Processing stays in this page. No JSON or path drafts, query scripts, or input keys, paths and values in analytics.

Page reading mode

The full guide also includes pitfalls, worked examples, snippets, FAQs, and related tools for checking results or troubleshooting.

About this tool

Flatten JSON into a map of typed paths and restore it without confusing object keys with array indexes. The default uses $["key"][0], keeps empty keys, delimiter-containing keys, empty containers and root scalars, and represents the root as $. Unflattening rejects equivalent or conflicting paths, mixed object/array nodes and sparse indexes instead of overwriting or inventing values. Dot, slash and underscore paths remain available for a restricted legacy subset. Strict parsing rejects duplicate keys and numeric changes; use strings for exact large identifiers. Input is limited to 2 MiB and 128 levels, with an 8 MiB output cap. Processing stays in the page without input drafts.

Scenario Recipes

01

Round-trip a payload with ambiguous-looking keys

Goal: Keep a literal dotted key separate from nested members and an empty array.

  1. Paste {"a.b":1,"a":{"b":2},"empty":[]} and leave Flatten with Typed paths selected.
  2. Run and check three paths: $["a.b"], $["a"]["b"] and $["empty"]. Copy the full JSON map.
  3. Paste the copied map as input, select Unflatten and run. Compare the restored keys, types and values with the original.

Result: The literal a.b value stays 1, nested a.b stays 2 and empty stays an array; no path is overwritten.

Production Snippets

Dotted keys are distinct from nested paths

text

Input:
{"a.b":1,"a":{"b":2},"empty":[]}

Typed flatten output:
{
  "$[\"a.b\"]": 1,
  "$[\"a\"][\"b\"]": 2,
  "$[\"empty\"]": []
}

Root [] -> {"$":[]}
Object key "0" -> $["0"]
Array index 0 -> $[0]

Failure Clinic (Common Pitfalls)

Two fields collapse into one legacy key

Cause: A delimiter-only path cannot distinguish the literal key a.b from the nested members a then b. Numeric object keys can also look like array indexes.

Fix: Use typed paths for a reversible map. Legacy mode rejects ambiguous keys rather than silently overwriting them; changing a delimiter is safe only when the entire input fits its restricted subset.

An incomplete flat array appears to contain invented nulls

Cause: A map containing only $[2] leaves two unknown entries. A parent path and child path also cannot both define the same node.

Fix: Supply contiguous indexes from zero and one consistent node type. This tool rejects sparse or conflicting maps; represent a real null explicitly and an empty root with the $ leaf.

Frequently Asked Questions

How do typed paths preserve object keys and arrays?

An object member named 0 is $["0"], while array index zero is $[0]. A literal key a.b is $["a.b"], distinct from nested $["a"]["b"].

What happens to scalars and empty containers?

The root path is $. For example, [] flattens to {"$":[]} and null to {"$":null}. Nested empty objects and arrays remain leaf values and keep their types.

Which flat maps can be restored?

Use an object whose keys are supported paths and whose values are scalars or empty containers. Array indexes must be contiguous from zero. Equivalent paths, ancestor/leaf conflicts and mixed object/array nodes are rejected.

When should I choose a legacy delimiter?

Only when the receiving system needs dot, slash or underscore paths. Empty keys and keys containing the delimiter are rejected. With numeric array segments enabled, numeric object keys are rejected; with them disabled, arrays are rejected.

Will large numbers remain exact?

Integers must be within ±9007199254740991 and decimal text must serialize to the same decimal value. Duplicate keys, negative zero, overflow, underflow and rounded values are rejected. Quote large IDs and high-precision decimals before pasting.

What are the size and privacy limits?

Input is at most 2 MiB, 128 levels and 100000 values; paths are at most 8192 characters, indexes 0–99999 and serialized output 8 MiB. The page does not save JSON drafts or send keys, paths or values in analytics.

Keep browsing