PDFFlare
8 min read

How to Flatten Nested JSON to Dot-Notation Keys (and Back)

You're wiring up a React form with React Hook Form and the field paths it expects look like user.address.city, not the nested object you've got. Or you need to feed a config to a 12-factor app and the env vars want flat keys like DATABASE_HOST, not nested JSON. Or you're managing translations and your i18n library wants dot keys. All three problems have the same fix: flatten the nested JSON.

In this guide you'll learn how to flatten nested JSON to dot-notation keys (and unflatten back) using PDFFlare's JSON Flatten tool — with delimiter options for env-var, path-style, and custom formats. 100% browser-based, round-trip safe.

What Does Flattening JSON Mean?

Flattening collapses a nested JSON document into a single-level object whose keys describe the path to each leaf value. The structure becomes part of the key, not the shape:

Nested: { "user": { "name": "alice", "address": { "city": "NYC" } } }

Flat (dot delimiter): { "user.name": "alice", "user.address.city": "NYC" }

Arrays use bracket-index notation: { "tags": ["a", "b"] } becomes { "tags[0]": "a", "tags[1]": "b" }.

Unflattening is the reverse — take a flat dot-keyed object and rebuild the nested structure. Round-trip safe for the typical case.

Why Flatten Nested JSON?

  • Form data libraries: React Hook Form, Formik, and most form libs use flat path strings as field names. Flattening is the bridge between your domain model and the form layer.
  • Environment variables: 12-factor apps consume config as flat env vars. Convert nested config to flat with _ as the delimiter, set in your environment, parse back at startup.
  • Translation files: i18n libraries (i18next, react-intl) typically use dot keys. Authors write nested JSON for readability, the build flattens for runtime lookup.
  • Flat key-value stores: Redis, etcd, Consul KV — all flat. Flatten your config, store as flat keys, no nested structure to manage.
  • Spreadsheet exports:CSV is flat; nested JSON doesn't map cleanly. Flatten first, convert via JSON to CSV, import to Excel.
  • Logging and analytics: Many log indexers prefer flat key paths over deep nesting. Flatten before sending to keep search performant.

How to Flatten JSON (Step by Step)

  1. Open PDFFlare's JSON Flatten tool — no signup.
  2. Make sure direction is set to Flatten (the default).
  3. Pick a delimiter. Dot (.) is default; switch to underscore for env-var-style, slash for path-style, or Custom for anything else.
  4. Paste your nested JSON into the input pane.
  5. Click Convert. The output pane shows the flattened object with one entry per leaf.
  6. Copy or download. To go back: toggle direction to Unflatten, paste the flat object, click Convert. The Swap button moves output to input for round-tripping.

Delimiter Options Explained

  • Dot (.) — the default. The most common style. Works with React Hook Form, Lodash _.get, JSONPath, and most i18n libraries.
  • Underscore (_) — env-var style. { "database": { "host": "localhost" } } becomes { "database_host": "localhost" } — convert to uppercase and set as env var DATABASE_HOST.
  • Slash (/) — path style. Useful for JSON Pointer-like keys, Consul KV (which uses slash by convention), or any system that treats paths hierarchically.
  • Custom — anything you want. Type any string into the custom field. Common choices: __ (double underscore for env vars that contain single underscores), or :: (double colon).

Round-Trip Safety

Flatten then unflatten should reproduce the original JSON exactly. PDFFlare's tool handles the typical case faithfully:

  • Nested objects: Reconstructed exactly.
  • Arrays: Index-based paths preserve element order and length.
  • Scalar values: Strings, numbers, booleans, null — all preserved as-is.
  • Empty objects and arrays: Preserved as a single entry at their path so unflatten can rebuild them.

Handling Keys That Contain the Delimiter

If a key contains the active delimiter, flattening would create ambiguity — is a.b the path to b inside a, or a single key literally named a.b? PDFFlare's flatten tool wraps such keys in ["..."] so the round trip stays unambiguous:

Input: { "a.b": 1 } (with dot delimiter active)

Flat output: { "[\"a.b\"]": 1 }

Unflatten reads the bracket-quoted segment as a single key, restoring the original. Works for slashes, underscores, custom delimiters too.

Common Scenarios

React Hook Form Field Paths

Your domain model is { user: { profile: { firstName: '' } } }. React Hook Form's field name is user.profile.firstName. Flatten the model on read, unflatten on submit. Same data, two representations.

Helm Chart --set Flags

helm install --set app.replicas=3 --set app.image.tag=latest is equivalent to a small nested values.yaml. If you start with the nested form, flatten with dot delimiter to produce --set flags directly.

i18n Translation Keys

Authors write { "home": { "hero": { "title": "Welcome" } } } for readability. The runtime library wants flat keys like home.hero.title. Flatten as a build step.

12-Factor App Configs

Maintain config as nested JSON (easy to read), flatten with _ delimiter for env vars, set in your container, unflatten at startup. Best of both worlds.

Spreadsheet Exports

Need to share a nested API response with a spreadsheet user? Flatten first (so each leaf becomes its own column), then convert via JSON to CSV. Excel handles the result cleanly.

Database Migration Diff

Flatten the old and new schemas, then run them through JSON Diff. The flat form makes structural changes pop.

Lodash, Ramda, and Friends: When You Don't Need to Flatten

Flattening physically reshapes your data. Sometimes you don't need that — you just need to read or write a value at a path. Path-aware accessor libraries handle this without flattening:

  • Lodash _.get and _.set: _.get(obj, "a.b.c", defaultValue) reads a nested value by a dot path; _.set writes one (creating missing intermediate objects). No flattening needed.
  • Ramda R.path: Functional alternative with array-of-keys instead of dot strings: R.path(["a", "b", "c"], obj). Curryable, easy to compose.
  • Native optional chaining: Modern JS supports obj?.a?.b?.c for safe navigation. No library at all, just language. Best for known-shape access.

Rule of thumb: flatten when downstream needs flat keys (forms, env vars, key-value stores). Use accessor libraries when your code needs to read or write paths but the data stays nested.

Performance: When to Flatten and When Not To

Flattening allocates a new object roughly the size of every leaf in the source. For typical configs and API responses this is fine. A few cases where it matters:

  • Small documents (under ~10 KB): Flatten freely. Performance cost is negligible.
  • Medium documents (10 KB - 1 MB):Flatten on demand, not on every call. Cache the flat form if you'll access it repeatedly.
  • Large documents (above ~10 MB): Flattening doubles memory use during the transformation. Use Lodash _.get(obj, 'a.b.c') on the nested form for individual lookups instead — same path syntax, no allocation.
  • Streaming data:Don't flatten. Use a streaming JSON parser and a path-aware visitor instead. PDFFlare's tool isn't designed for streaming.

Common Mistakes

  • Choosing a delimiter that appears in your keys. If your keys contain dots and you flatten with dot delimiter, you'll either get bracket-quoted segments (PDFFlare's behaviour) or ambiguous paths (other tools). Pick a delimiter that doesn't collide with key content.
  • Unflatten in a different tool with a different delimiter convention. If you flatten with dot in PDFFlare and try to unflatten in another library configured for slashes, nothing unflattens. Round-trip in the same tool, or document the delimiter choice clearly.
  • Forgetting that arrays use bracket-index, not dot-index. tags[0], not tags.0. PDFFlare follows the standard convention; some libraries differ.
  • Treating flatten as lossless for streaming data. Flatten on a 100-MB log file produces an even bigger flat object. Streaming flatten is a different tool — for huge data, use a scripting language with a streaming JSON parser.
  • Mixing delimiters within one document.One document, one delimiter. Mixing means unflatten can't parse the result correctly.

Best Practices

  • Pick a delimiter and document it.A README note saying “all flat configs use dot delimiter” saves future-you confusion.
  • Flatten as a build step, not at runtime. Translation files, env-var configs — generate the flat form once during build, ship the flat form, save runtime parsing cost.
  • Use Dot Notation libraries on flat data. Lodash _.get(obj, "a.b.c")works on the nested form too — sometimes you don't need to flatten, you just need a path-aware getter.
  • Validate flat input keys against expectations. If you're consuming flat input from an external source, validate that all expected paths are present — typos in flat keys silently produce missing values.

Flatten vs JSON Pointer vs JSONPath

Three ways to address values inside a JSON document. They look similar, but solve different problems:

  • Flatten (this tool): Materializes every leaf path as a key. Output is a new flat JSON object. Best for handing data to systems that natively expect flat keys.
  • JSON Pointer (RFC 6901): A path syntax (/user/address/city) used for $refin JSON Schema and OpenAPI. Doesn't flatten — just describes “where in the document.” Tools use it to resolve specific values.
  • JSONPath: A query language, not a flatten operation. $.user.address.city looks similar to a flat key, but you use it to extractvalues, not to re-shape the document. See PDFFlare's JSONPath Tester.

Rule of thumb: flatten when you need a new flat document; JSONPath when you need to query an existing nested document; JSON Pointer when you're writing schema $refs.

Edge Cases Worth Testing

  • Mixed-type arrays: Flattening {"items": [1, "two", {"a": 3}]} produces three entries with different value types — items[0]: 1, items[1]: "two", items[2].a: 3. Round-trip safe.
  • Nested arrays: {"matrix": [[1,2],[3,4]]} flattens to four entries with bracket-bracket paths like matrix[0][0].
  • Boolean and null leaves: Preserved as their actual values, not stringified.
  • Numeric string keys: A key like {"42": "answer"} stays a string key in the flat output — JSON object keys are always strings.

Privacy: Your JSON Stays on Your Device

PDFFlare's JSON Flatten runs entirely in your browser. The flatten and unflatten logic is JavaScript executed locally — your JSON never uploads anywhere. Safe for production configs containing secrets, customer data, or anything sensitive.

Wrapping Up

Flat dot-notation is the lowest-common-denominator format for consuming nested data — works in form libraries, env vars, key-value stores, translation files, and spreadsheets. A solid bi-directional flatten/unflatten with delimiter options handles 95% of the cases you'll hit.

Got nested JSON that needs to land somewhere flat? Open PDFFlare's JSON Flatten tool and pick the delimiter that matches your downstream consumer.

Related Tools

  • JSON to CSV — flatten first, then export to Excel-friendly CSV
  • JSON Diff — diff flattened forms for clear structural diffs
  • JSON Formatter — format flat or nested output for human review
  • JSON Path — query nested data without flattening when paths suffice