Skip to content

Instantly share code, notes, and snippets.

@iGoodie
Last active May 31, 2022 16:38
Show Gist options
  • Save iGoodie/a09b78110473e463bde8b26484bc4b82 to your computer and use it in GitHub Desktop.
Save iGoodie/a09b78110473e463bde8b26484bc4b82 to your computer and use it in GitHub Desktop.
Flatten JavaScript Object by Mapping Keys Recursively
export function flattenObject(
obj: object,
opts: {
prefix?: string;
postfix?: string;
delimiter?: string;
wordExtractor?: (text: string) => string[];
}
) {
const flattened: Record<string, any> = {};
const wordExtractor = opts.wordExtractor || extractWordsFromCamelCase;
const prefix = opts.prefix || "";
const postfix = opts.postfix || "";
const delimiter = opts.delimiter || ".";
for (let propertyName of Object.keys(obj)) {
const targetProperty = obj[propertyName];
const flattenedKey =
prefix + wordExtractor(propertyName).join(delimiter);
if (typeof targetProperty === "object") {
const flattenedTarget = flattenObject(targetProperty, { delimiter });
for (const [k, v] of Object.entries(flattenedTarget)) {
flattened[flattenedKey + delimiter + k + postfix] = v;
}
} else {
flattened[flattenedKey + postfix] = targetProperty;
}
}
return flattened;
}
// Default way to extract words. Assumes input string is in camelCase
function extractWordsFromCamelCase(text: string) {
return (text.charAt(0).toLowerCase() + text.substring(1))
.replace(/([A-Z])/g, ",$1")
.split(",")
.map((word) => word.toLowerCase());
}
@iGoodie
Copy link
Author

iGoodie commented May 31, 2022

If you'd like arrays not to be flattened by their indices,
Simply replace typeof targetProperty === "object" check with targetProperty?.constructor.name === 'Object'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment