Created
April 29, 2019 20:55
-
-
Save lac5/d8180ac77f978cf3c894914a198a4afa to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** @typedef {string|boolean|number|Function|void} nonObject */ | |
/** | |
* @typedef {[string, nonObject]} DenestedRow | |
* @property {string} path The dot/bracket notation of the variable. (Example: `a.b[0].c["d-e"].f`). Same as `this[0]`. | |
* @property {object} parent The object that holds this variable. | |
* @property {string} key The key to this variable. (`this.parent[this.key] === this[1]`) | |
*/ | |
/** | |
* Concatenates an object and nested objects into a single key-value array. | |
* Useful for turning an object into a table. | |
* @param {object} object | |
* @return {DenestedRow[]} | |
*/ | |
export default function denest(object) { | |
/** @type {DenestedRow[]} */ | |
const table = []; | |
/** @type {string[]} */ | |
const path = []; | |
/** @type {[object, string[], number][]} */ | |
const state = [[ | |
object, | |
Object.keys(object), | |
0 | |
]]; | |
const goodKey = /^[a-zA-Z_][a-zA-Z0-9_]*$/; | |
loop: do { | |
const object = state[0][0]; | |
const length = state[0][1].length; | |
for (let i = state[0][2]; i < length; i++) { | |
const k = state[0][1][i]; | |
if (object[k] && typeof object[k] === 'object') { | |
state[0][2] = i + 1; | |
path.push( | |
goodKey.test(k) | |
? (path.length > 0 ? '.' : '') + k | |
: '['+ (isNaN(k) ? JSON.stringify(k) : k) +']' | |
); | |
state.unshift([ | |
object[k], | |
Object.keys(object[k]), | |
0 | |
]); | |
continue loop; | |
} else { | |
/** @type {DenestedRow} */ | |
const row = [ | |
path.concat( | |
goodKey.test(k) | |
? (path.length > 0 ? '.' : '') + k | |
: '['+ (isNaN(k) ? JSON.stringify(k) : k) +']' | |
).join(''), | |
object[k] | |
]; | |
row.path = row[0]; | |
row.parent = object; | |
row.key = k; | |
table.push(row); | |
} | |
} | |
path.pop(); | |
state.shift(); | |
} while (state.length > 0); | |
return table; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment