How to use the JSON unflattener
- Paste a flat object into Flat JSON. Each key is a path, each value is what goes at the end of it.
- Set the Separator used in your keys:
.by default, or something like/or__. - Keep Numeric segments become array indexes ticked to rebuild arrays, or untick it to keep number-like parts as object keys.
- Choose an Indent and copy or download the Nested JSON.
What it does and when to use it
Flat key/value data is everywhere: translation files exported from a localisation platform, spreadsheet columns named address.city, form fields named items[0].qty, environment variables with double underscores, or the output of a flattening step you ran earlier. Most programs want the nested shape. This tool builds it without a script.
It is the exact reverse of the JSON flattener when you use the same separator and index style. After rebuilding, tidy the result with the JSON key sorter or check it against a schema with the JSON Schema validator.
How it works
Each key is split on the separator. Inside each part, bracketed numbers such as [0] are pulled out as array positions. With the numeric option on, a part that is only digits is also an array position. The tool then walks from the root, creating an object or an array for each missing step, depending on whether the next part is a name or a number, and puts the value at the end. If the very first part of the first key is a number, the root itself becomes an array, so {"0.id":1,"1.id":2} turns into [{"id":1},{"id":2}].
Keys are processed in the order they appear. Values are copied unchanged, so nested values already inside the flat object stay as they are. All of this happens in your browser.
Worked examples
Translation keys with one bracket index:
{"checkout.title":"Pay now","checkout.button.pay":"Pay",
"checkout.button.cancel":"Cancel","errors[0]":"Card declined"}
{"checkout":{"title":"Pay now","button":{"pay":"Pay","cancel":"Cancel"}},"errors":["Card declined"]}
Environment-style keys with Separator __: {"db__host":"localhost","db__port":5432} gives {"db":{"host":"localhost","port":5432}}.
A postcode kept as a key, with the numeric option unticked: {"zip.0":"x"} gives {"zip":{"0":"x"}}. With it ticked, the same input would give an array.
Limits and tips
- The input must be an object. An array returns a message asking for a flat object.
- A separator that also appears inside real key names splits them too. Pick one that does not occur in your names.
- A large index such as
list.100000creates an array with that many null items before it.
Frequently asked questions
Why did a number in my key turn into an array?
Why are there nulls in my array?
What if both "a" and "a.b" are keys?
Does it understand bracket indexes?
How do we know nothing is uploaded? Test it yourself on the privacy proof page.