How to unflatten flat json to rebuild rest api payloads
- Step 1Collect the flat key-value payload — Copy the flat JSON from your form serializer, CSV-to-JSON result, or query-string parser. Keys like
user_address_cityoruser.address.citywill be rebuilt into nested objects. - Step 2Set the Key delimiter to the one your keys use — Type the separator your flat keys use into the single Key delimiter field —
_for underscore serializers,.for dot-notation. Only this one string is used to split; there is no bracket-notation mode. - Step 3Convert bracket-style keys before unflattening — If your form produced
user[address][city], rename those keys to a single-delimiter form (e.g.user.address.city) first with the JSON Key Renamer, because the unflattener splits on one delimiter, not on brackets. - Step 4Drop or paste the JSON and run — Drop the
.jsonfile (free tier up to 2 MB) and click Unflatten JSON. Processing is local — the payload is never uploaded. - Step 5Cast types the API requires — Form values arrive as strings. If the API expects numbers or booleans (
"age": 25,"active": true), cast those fields in your request builder after unflattening — the tool does not infer types. - Step 6Send the nested body — Copy the output or download
<name>.nested.json, thenfetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(nested) }).
Flat key conventions and how to feed them in
The unflattener splits on exactly one delimiter string. Bracket and mixed conventions need normalising first.
| Source convention | Example flat key | What to do |
|---|---|---|
| Underscore serializer | user_address_city | Set delimiter to _ and run |
| Dot-notation parser | user.address.city | Default delimiter . works as-is |
| PHP/Rails bracket form | user[address][city] | Rename to user.address.city first — brackets are not parsed |
| Indexed array field | tags.0, tags.1 | Rebuilds as { "0": ..., "1": ... } map — convert to array if the API needs one |
| Double-delimiter convention | user__address__city | Set delimiter to __ (up to 3 chars allowed) |
Value handling for API bodies
Values are preserved exactly as they appear in the flat JSON. There is no coercion step.
| Flat value | After unflatten | If the API needs a different type |
|---|---|---|
"age": "25" | "25" (string) | Cast to number in your request builder |
"active": "true" | "true" (string) | Cast to boolean in your request builder |
"zip": "01970" | "01970" (string, leading zero kept) | Leave as string — casting would lose the zero |
"price": 19.99 | 19.99 (number, already typed) | Already a JSON number — no action |
"note": null | null | Preserved; strip with JSON Null Stripper if the API rejects nulls |
Cookbook
Real before/after payloads from form and CSV pipelines. The delimiter shown is what you would type in the Key delimiter field.
Underscore form data to a nested user body
ExampleA form serializer flattened the user object with underscores. Set the delimiter to _ to rebuild the nested body the API wants.
Key delimiter: _
Flat input:
{
"user_name": "Alice",
"user_address_city": "London",
"user_address_zip": "EC1A"
}
Output:
{
"user": {
"name": "Alice",
"address": { "city": "London", "zip": "EC1A" }
}
}Bracket-notation form keys must be renamed first
ExamplePHP/Rails forms emit user[address][city]. The unflattener will not parse the brackets, so normalise the keys to a single delimiter before running.
Raw form keys (NOT directly supported):
{ "user[address][city]": "London" }
Step 1 — JSON Key Renamer: user[address][city] → user.address.city
Step 2 — Unflatten (delimiter .):
{ "user": { "address": { "city": "London" } } }Indexed keys rebuild as a map, not an array
ExampleA flat tags.0 / tags.1 does not become [...]. If the API expects an array body, convert the resulting map afterward.
Flat input:
{ "tags.0": "news", "tags.1": "promo" }
Output:
{ "tags": { "0": "news", "1": "promo" } }
API wants: "tags": ["news", "promo"]
→ Object.values(payload.tags) before sendingStrings stay strings — cast before sending
ExampleEvery form field is a string. The unflattener preserves that, so cast numeric/boolean fields in your builder.
Flat input:
{ "order_total": "19.99", "order_paid": "true" }
Output:
{ "order": { "total": "19.99", "paid": "true" } }
In code:
payload.order.total = Number(payload.order.total);
payload.order.paid = payload.order.paid === 'true';POST the rebuilt body
ExampleDrop the nested JSON into a fetch call once types are cast.
const body = require('./payload.nested.json');
await fetch('https://api.example.com/v1/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});Errors and edge cases
Real errors and silent failures sourced from each platform's own documentation. Match the wording to the row, fix what the row says to fix.
Bracket-notation keys like user[address][city]
Not parsedBrackets are treated as ordinary characters in the key. Only the single delimiter splits keys. Rename bracket keys to a single-delimiter form with the JSON Key Renamer first.
Numeric segments (tags.0, tags.1)
By designRebuilt as object keys "0", "1", not as a JSON array. If your API needs an array body, map the resulting object to an array before sending.
Form value is a numeric or boolean string
Preserved as string"25" and "true" stay strings. Cast them in your request builder; the JSON Format Fixer repairs JSON syntax but does not change value types.
Leading-zero values like zip 01970
PreservedKept exactly as the string "01970". This is correct — never cast these to numbers or you lose the leading zero.
Top-level field collides with a nested path
Last write winsIf both user (scalar) and user.name exist, the one written later determines the result. Reorder or rename to keep the field you intend to send.
Delimiter appears inside a real key segment
Over-splitsA key like coupon_code_2026 with delimiter _ over-splits into nested objects. Choose a delimiter that does not collide, or rename keys first.
Input is an array of payloads
Not the expected inputThe tool unflattens one flat object per run. Process each payload object separately rather than passing an array.
Malformed JSON from a serializer (single quotes, trailing comma)
Parse errorThe input must be valid JSON. Repair it with the JSON Format Fixer before unflattening.
Payload over the free 2 MB limit
Blocked on freeFree JSON tier caps files at 2 MB. Upgrade to Pro to lift the file-size limit.
Frequently asked questions
Does the unflattener understand bracket notation like user[address][city]?
No. It splits keys on a single configurable delimiter only. Bracket-style keys are treated as literal text. Rename them to a single-delimiter form (e.g. user.address.city) with the JSON Key Renamer, then unflatten.
Will it cast my form's numeric and boolean strings back to real types?
No. Values are preserved exactly, so "age": "25" stays the string "25". Cast the fields the API requires in your request builder after unflattening. The JSON Format Fixer fixes syntax, not value types.
How are array fields like tags[0] and tags[1] reconstructed?
Bracket keys are not parsed at all. If your keys use a delimiter instead (tags.0, tags.1), they rebuild as the object { tags: { "0": ..., "1": ... } } — a map, not an array. Convert it to an array (e.g. Object.values) if the API expects one.
Which delimiter should I pick for form data?
Match whatever your serializer produced. Underscore serializers use _; query-string and dot parsers use .. The Key delimiter field accepts up to 3 characters for conventions like __.
Is the form data or API payload sent to JAD Apps?
No. Unflattening runs entirely in your browser. Form submissions, personal data, and API request payloads are never uploaded to JAD Apps servers.
Can I unflatten several payloads in one run?
No. The tool processes one flat JSON object per run. Run each payload separately, or script the lib function over a list in your own pipeline.
What happens if a top-level field and a nested path collide?
Last write wins. A scalar parent is overwritten when a deeper path arrives later, and vice versa. The output is deterministic for a given key order — reorder or rename to control which field survives.
Can I control the indentation of the output body?
No. Output is always 2-space indented. For a compact request body, minify the result with the JSON Minifier.
Where do flat payloads usually come from?
HTML form serializers, URL query-string parsers, and CSV-to-JSON conversions. If you started from a CSV, the CSV to JSON tool produces the flat object that this tool then nests.
What is the file-size limit?
2 MB per file on the free JSON tier. Pro removes the file-size limit. This is a Pro tool.
How do I send the result with axios instead of fetch?
axios.post(url, nested) — axios serializes the object and sets the JSON content type for you. Cast any string fields the API needs as numbers or booleans first.
My POST is rejected for null fields — what now?
Some APIs reject explicit nulls. The unflattener preserves nulls; strip them after unflattening with the JSON Null Stripper before sending.
Privacy first
Conversion runs locally in your browser. No file is uploaded — only metadata counters are saved for signed-in dashboard stats.