Nested JSON is easy to read but hard to process. When loading data into a spreadsheet, database table, or analytics tool, you often need a flat structure — one level of keys with no nested objects. This guide shows you how to flatten JSON in both JavaScript and Python.
What Does "Flattening" Mean?
Flattening converts nested keys into dot-separated (or underscore-separated) keys at the top level.
// Before (nested)
{
"user": {
"name": "Alice",
"address": {
"city": "Berlin",
"zip": "10115"
}
}
}
// After (flat)
{
"user.name": "Alice",
"user.address.city": "Berlin",
"user.address.zip": "10115"
}
Flatten JSON in JavaScript
A recursive function that walks every key and builds dot-notation paths:
function flattenJSON(obj, prefix = "", result = {}) {
for (const key in obj) {
if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;
const fullKey = prefix ? `${prefix}.${key}` : key;
const value = obj[key];
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
// Recurse into nested objects
flattenJSON(value, fullKey, result);
} else {
// Primitive value or array — store as-is
result[fullKey] = value;
}
}
return result;
}
const nested = {
user: {
name: "Alice",
address: { city: "Berlin", zip: "10115" }
},
score: 95
};
console.log(flattenJSON(nested));
// {
// "user.name": "Alice",
// "user.address.city": "Berlin",
// "user.address.zip": "10115",
// "score": 95
// }
Handling Arrays During Flattening
Arrays can be treated in two ways: keep them as-is (default above), or expand each element with an index key.
function flattenDeep(obj, prefix = "", result = {}) {
for (const key in obj) {
if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;
const fullKey = prefix ? `${prefix}.${key}` : key;
const value = obj[key];
if (value !== null && typeof value === "object") {
// Recurse into both objects AND arrays
flattenDeep(value, fullKey, result);
} else {
result[fullKey] = value;
}
}
return result;
}
const data = { tags: ["json", "api", "rest"] };
console.log(flattenDeep(data));
// { "tags.0": "json", "tags.1": "api", "tags.2": "rest" }
Flatten JSON in Python
def flatten_json(obj, prefix="", sep="."):
result = {}
for key, value in obj.items():
full_key = f"{prefix}{sep}{key}" if prefix else key
if isinstance(value, dict):
# Recurse into nested dicts
result.update(flatten_json(value, full_key, sep))
else:
result[full_key] = value
return result
nested = {
"user": {
"name": "Alice",
"address": {"city": "Berlin", "zip": "10115"}
},
"score": 95
}
print(flatten_json(nested))
# {'user.name': 'Alice', 'user.address.city': 'Berlin',
# 'user.address.zip': '10115', 'score': 95}
Using pandas.json_normalize (Python)
If you're already using pandas, json_normalize flattens JSON into a DataFrame in one line.
from pandas import json_normalize
data = [
{"user": {"name": "Alice", "city": "Berlin"}, "score": 95},
{"user": {"name": "Bob", "city": "Paris"}, "score": 87}
]
df = json_normalize(data)
print(df)
# user.name user.city score
# 0 Alice Berlin 95
# 1 Bob Paris 87
The sep parameter controls the separator character (default is .). Use sep="_" for underscore-separated keys that work better as DataFrame column names.
Unflattening — Reverting to Nested
Sometimes you need the reverse operation — rebuilding a nested structure from flat keys:
function unflattenJSON(flat) {
const result = {};
for (const [key, value] of Object.entries(flat)) {
const parts = key.split(".");
let current = result;
for (let i = 0; i < parts.length - 1; i++) {
if (!current[parts[i]]) current[parts[i]] = {};
current = current[parts[i]];
}
current[parts[parts.length - 1]] = value;
}
return result;
}
Try Our JSON Tools
Want to explore nested JSON before writing code to flatten it?