Unflatten dot keys to nested JSON online
Rebuild a nested record from flat dotted names: user.contact.email goes back inside contact, inside user, while active and the score of 42 stay at the top level. In the example, 5 flat entries are processed. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Runs in your browser. Free, unlimited — your data never leaves this page.
Turn dotted paths into an ordinary nested document
Each property name is interpreted as a path whose segments are separated by periods. For example, account.profile.name becomes the name property inside profile, which is inside account. A key without a period remains at the top level.
The result includes the reconstructed document under json and a keys count showing how many flat properties were processed. Numeric-looking path segments are treated as ordinary object keys rather than array indexes, so the transformation never guesses a collection shape that the input did not explicitly describe. The transformation is deterministic, performs no network requests, and does not depend on locale, clock time, or property insertion side effects for its meaning.
Detect conflicting paths before data is lost
Unflattening becomes dangerous when one key says a path is a final value while another needs that same path to be an object. Explicit objects may be extended by dotted descendants when their existing properties do not collide, so settings set to an object can coexist with settings.theme set to a new member. Empty keys, leading or trailing periods, and doubled periods are rejected because they create unnamed path segments.
The special JavaScript property names __proto__, prototype, and constructor are rejected at every level, including within supplied object values, to prevent prototype-related surprises. These checks make failures visible early and preserve the important guarantee that a successful result has one unambiguous source for every output location.
Use the result in migrations and application pipelines
Flat keys appear frequently at system boundaries. A validation failure then points to the source record rather than allowing an incomplete structure to travel farther through the pipeline. For batch work, call the capability once per flat record because the billing unit is an item and each response describes exactly one reconstructed document.
Conversely, strings containing periods are safe as values; only property names are interpreted as paths.
FAQ
What does it cost?
You can also run the transformation in your browser on this page.
Are numeric path segments converted into arrays?
No. Every segment is preserved as an object key, avoiding guesses about whether a numeric name represents an index or an identifier.
Are value types preserved?
Yes. Strings, finite numbers, booleans, nulls, arrays, and objects are copied without type coercion.
Can a key contain an empty path segment?
No. Empty keys, doubled periods, and leading or trailing periods are rejected as ambiguous paths.
What happens if two names clash, like user and user.name?
The input is rejected with a clear error instead of keeping whichever name happened to come last. One value cannot be both a final value and a group at the same time, so every location in a successful result has exactly one source.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/data/unflatten-to-json \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"flat":{"user.name":"Ada","user.contact.email":"ada@example.com","active":true}}'const res = await fetch("https://api.kit.forhosting.com/data/unflatten-to-json", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"flat": {
"user.name": "Ada",
"user.contact.email": "ada@example.com",
"active": true
}
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/data/unflatten-to-json",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"flat": {
"user.name": "Ada",
"user.contact.email": "ada@example.com",
"active": true
}
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/data/unflatten-to-json", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"flat":{"user.name":"Ada","user.contact.email":"ada@example.com","active":true}}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"flat":{"user.name":"Ada","user.contact.email":"ada@example.com","active":true}}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/data/unflatten-to-json", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"flat": {
"user.name": "Ada",
"user.contact.email": "ada@example.com",
"active": true
}
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "data.unflatten_to_json",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_mb | 25 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
Turn a flat JSON object such as {"account.name":"Ada"} into the nested structure your application actually expects. This deterministic unflattening tool expands every dot-separated key, preserves strings, numbers, booleans, nulls, arrays, and object values, and reports ambiguous paths instead of silently overwriting data. It is useful when environment variables, form exports, configuration systems, analytics tools, or database queries produce flat records that must be restored before validation or processing.
Convert dot paths into an ordinary JSON document
Provide one JSON object in the flat field. Values are not coerced: a number stays a number, false stays a boolean, null stays null, and arrays retain their order and contents. This makes the output stable for configuration data, database aliases, and form submissions. Use valid JSON values and quote every property name in the request.
Detect conflicting paths before data is lost
An input containing user as a string and user.name as another value cannot represent both facts in one JSON structure. This capability rejects that input with an invalid input error instead of choosing whichever property happens to be visited last. It also rejects collisions inside explicit object values.
Use the result in migrations and application pipelines
SQL queries often emit aliases such as customer.address.city; logging and analytics platforms flatten nested events for indexing; HTML forms encode grouped controls with dotted names; and deployment systems represent structured settings as individual variables. Place this conversion immediately after reading that boundary format and before applying a nested JSON schema. Because values are copied without string parsing or type inference, callers should parse any intentionally encoded JSON strings before submitting them.
Integration use cases
Restore database query aliases
Turn columns such as customer.name and customer.address.city into the nested customer object expected by an API.
Prepare configuration for validation
Rebuild nested settings from flattened configuration keys before applying a JSON Schema or application defaults.
Normalize form and event records
Convert dotted field names from forms, logs, or analytics exports into ordinary JSON for downstream processing.
Technical questions
What happens when one key is a prefix of another?
If the prefix holds a non-object value, the request fails with invalid_input because both paths cannot exist in one JSON document.