How to Flatten an Object in JavaScript or TypeScript
Jasser Mark Arioste
Hello, hustlers! In this article, you'll learn how to flatten objects in JavaScript and Typescript. You will also learn other variations depending on the browser support.
Flatten this object:
const obj = { slug: 'javascript-tutorial', content: { title: 'Javascript Tutorial', body: 'Hello, world.', }, stats: { views: 100, shares: 200, otherStat: { test: 1, }, }, tags: ['javascript', 'typescrpt', 'nextjs'], };
123456789101112131415
Into this:
{ "slug": "javascript-tutorial", "content.title": "Javascript Tutorial", "content.body": "Hello, world.", "stats.views": 100, "stats.shares": 200, "stats.otherStat.test": 1, "tags.0": "javascript", "tags.1": "typescript", "tags.2": "nextjs" }
1234567891011
This transforms the keys into the dot notation used by MongoDB.
Why would you need to flatten an object? #
Flattening an object is beneficial in a lot of scenarios. It allows you to manipulate the object more easily. It also allows you to easily map through all the properties.
I'm not sure about other databases, but if you're using MongoDB as your database, it allows you to safely update your data using the $set
operator.
It's also useful if you have a GraphQL server and you only want to project the queried fields to save some bandwidth.
How to flatten an object in TypeScript? #
Since a nested object is a tree data structure, the best way to go through all the nested properties is to use recursion.
Here is the code and it uses a modern es6 implementation, I'll explain it afterwards:
// flattenObject.ts export const flattenObject = (obj:Object, parentKey?:string) => { let result = {}; Object.keys(obj).forEach((key) => { const value = obj[key]; const _key = parentKey ? parentKey + '.' + key : key; if (typeof value === 'object') { result = { ...result, ...flattenObject(value, _key) }; } else { result[_key] = value; } console.log(`parentKey: "${parentKey}", _key: "${_key}"`); }); return result; };
1234567891011121314151617
Explanation:
- Line #2-3,14, We declare a function
flattenObject(obj:Object, parentKey?: string)
that returns theresult
object. - Line #4: We use Object.keys() to loop through all the keys of
obj
- Line #5: We store the value to a variable for more readability.
- Line #6: We store the key, if there's a
parentKey
, we prepend theparentKey
to the current key. For example ifparentKey="stats"
and currentkey="views"
, this becomes"stats.views"
- Line #7-8: If the property is an object, we call
flattenObject
recursively to get a flattened version of the child object. We assign all the properties of the child object to the result object using the spread operator. We also pass the calculated_key
, to retain the path of its ancestor objects. - Line 10: If the property is not an Object, we store the value using the calculated
_key
. If this is the root object, then it would not have a parent key. - Line 13: A console.log to see the result for each iteration. This is to show you how each property is traversed.
- Line 14: Once we finished traversing through all the properties, we return the
result
.
If you check the logs the result will be this.
parentKey: "undefined", _key: "slug" parentKey: "content", _key: "content.title" parentKey: "content", _key: "content.body" parentKey: "undefined", _key: "content" parentKey: "stats", _key: "stats.views" parentKey: "stats", _key: "stats.shares" parentKey: "stats.otherStat", _key: "stats.otherStat.test" parentKey: "stats", _key: "stats.otherStat" parentKey: "undefined", _key: "stats" parentKey: "tags", _key: "tags.0" parentKey: "tags", _key: "tags.1" parentKey: "tags", _key: "tags.2" parentKey: "undefined", _key: "tags"
123456789101112
The above logs show which property is traversed in each iteration.
How to flatten an object in JavaScript? #
The code is similar to typescript, we only need to remove the type anotations.
export const flattenObject = (obj, parentKey) => { let result = {}; Object.keys(obj).forEach((key) => { const value = obj[key]; const _key = parentKey ? parentKey + '.' + key : key; if (typeof value === 'object') { result = { ...result, ...flattenObject(value, _key) }; } else { result[_key] = value; } console.log(`parentKey: "${parentKey}", _key: "${_key}"`); }); return result; };
12345678910111213141516
Other Versions #
If you're using ES2017, you can use Object.entries to further simplify the code:
export const flattenObject = (obj: Object, parentKey?: string) => { let result = {}; Object.entries(obj).forEach(([key, value]) => { const _key = parentKey ? parentKey + '.' + key : key; if (typeof value === 'object') { result = { ...result, ...flattenObject(value, _key) }; } else { result[_key] = value; } }); return result; };
1234567891011121314
If you have no access to typescript and need to support older browsers, you can use the JavaScript for..in operator to traverse and assign the properties to the result
object:
export function flattenObject(obj: Object, parentKey?: string) { let result: Object = {}; for (let key in obj) { if (!obj.hasOwnProperty(key)) continue; const value = obj[key]; const _key = parentKey ? parentKey + '.' + key : key; if (typeof value == 'object') { let childObject = flattenObject(value, _key); for (let childKey in childObject) { if (!childObject.hasOwnProperty(childKey)) continue; result[childKey] = childObject[childKey]; } } else { result[_key] = value; } } return result; }
12345678910111213141516171819
What else can we do? #
Depending what you need, you might not need to flatten the array. You can just add a condition to check if the value is not an array using Array.isArray(obj)
.
Another thing you can do is, you can use the flattened keys, in combination with lodash.set method to easily create / set properties in another object.
Conclusion #
We learned how to flatten an object in typescript and JavaScript, along with other ES versions that we might want to consider using.
We also learned the benefits and the uses when flattening an array in JavaScript and Typescript. Furthermore, we learned a little bit about recursive functions. Recursive functions are very powerful in any programming language, make sure you know it well!
If you like this tutorial, please leave a like or share this article. For future tutorials like this, please subscribe to our newsletter or follow me on Twitter.
Related Posts #
Further improve your JavaScript knowledge by reading these posts!
Credits: Image by 畅 苏 from Pixabay