-
-
Save penguinboy/762197 to your computer and use it in GitHub Desktop.
var flattenObject = function(ob) { | |
var toReturn = {}; | |
for (var i in ob) { | |
if (!ob.hasOwnProperty(i)) continue; | |
if ((typeof ob[i]) == 'object') { | |
var flatObject = flattenObject(ob[i]); | |
for (var x in flatObject) { | |
if (!flatObject.hasOwnProperty(x)) continue; | |
toReturn[i + '.' + x] = flatObject[x]; | |
} | |
} else { | |
toReturn[i] = ob[i]; | |
} | |
} | |
return toReturn; | |
}; |
I'm wondering how to do it similarly to what @gitty-git-git asks.
But i want to keep arrays as they are unless they have objects, in that case flatten the objects.
For example this:
flatten({a:{b:2},c:[{e:{f:4}}]})
{
"a.b": 2,
"c": [
{
"e.f": 4
}
]
}
Anyone has an idea? @gitty-git-git did you find a way to do yours?
slighlty modified from @codeBelt to output array indices as [0]
instead of as property .0
export function flatten<T extends Record<string, any>>(object: T, path: string | null = null, separator = '.'): T {
return Object.keys(object).reduce((acc: T, key: string): T => {
const value = object[key];
const newPath = Array.isArray(object)
? `${path ? path : ''}[${key}]`
: [path, key].filter(Boolean).join(separator);
const isObject = [
typeof value === 'object',
value !== null,
!(value instanceof Date),
!(value instanceof RegExp),
!(Array.isArray(value) && value.length === 0),
].every(Boolean);
return isObject
? { ...acc, ...flatten(value, newPath, separator) }
: { ...acc, [newPath]: value };
}, {} as T);
}
Forked example: https://stackblitz.com/edit/typescript-pwsl83
I have put together a simple module, Flatify-obj based on this original gist with some additional tweaks and tests.
Usage
const flattenObject = require('flatify-obj');
flattenObject({foo: {bar: {unicorn: '🦄'}}})
//=> { 'foo.bar.unicorn': '🦄' }
flattenObject({foo: {unicorn: '🦄'}, bar: 'unicorn'}, {onlyLeaves: true});
//=> {unicorn: '🦄', bar: 'unicorn'}
For additional features PRs are welcome 🦄
Another one written in TypeScript: tree-to-flat-map.
you are the best!
@danzelbel like a charm!
Jewel!
This is my implementation, it just flattens every object in the parent object into one, without keying them with object.key
.
Working example
Code:
function flatten(obj = {}) {
const doneObject = {}
for (const [k, v] of Object.entries(obj)) {
if (typeof v == "object" && !(v instanceof Date) && !Array.isArray(v) && !(v instanceof regExp)) {
Object.assign(doneObject, flatten(v))
} else {
doneObject[k] = v
}
}
return doneObject
}
Thank you for the original implementation!
A version that leaves undefined behind, array as is and don't try to flatten primitive objects (Number, Boolean, BigInt and String essentially) :
const flatten = <T extends Record<string, any>>(object: T, path?: string): Record<string, any> =>
Object.entries(object).reduce((acc, [key, val]) => {
if (val === undefined) return acc;
if (path) key = `${path}.${key}`;
if (typeof val === 'object' && val !== null && !(val instanceof Date) && !(val instanceof RegExp) && !Array.isArray(val)) {
if (val !== val.valueOf()) {
return { ...acc, [key]: val.valueOf() };
}
return { ...acc, ...flatten(val, key) };
}
return { ...acc, [key]: val };
}, {});
What an awesome thread. Thanks to everyone here!
I made an improvement from @x47188 version to handle
null
values and empty[]
arrays. Also added theDate
andRegex
object for the hell of it.Example: https://stackblitz.com/edit/typescript-shdjoq