| var isBuffer = require('is-buffer') |
| |
| module.exports = flatten |
| flatten.flatten = flatten |
| flatten.unflatten = unflatten |
| |
| function flatten (target, opts) { |
| opts = opts || {} |
| |
| var delimiter = opts.delimiter || '.' |
| var maxDepth = opts.maxDepth |
| var output = {} |
| |
| function step (object, prev, currentDepth) { |
| currentDepth = currentDepth || 1 |
| Object.keys(object).forEach(function (key) { |
| var value = object[key] |
| var isarray = opts.safe && Array.isArray(value) |
| var type = Object.prototype.toString.call(value) |
| var isbuffer = isBuffer(value) |
| var isobject = ( |
| type === '[object Object]' || |
| type === '[object Array]' |
| ) |
| |
| var newKey = prev |
| ? prev + delimiter + key |
| : key |
| |
| if (!isarray && !isbuffer && isobject && Object.keys(value).length && |
| (!opts.maxDepth || currentDepth < maxDepth)) { |
| return step(value, newKey, currentDepth + 1) |
| } |
| |
| output[newKey] = value |
| }) |
| } |
| |
| step(target) |
| |
| return output |
| } |
| |
| function unflatten (target, opts) { |
| opts = opts || {} |
| |
| var delimiter = opts.delimiter || '.' |
| var overwrite = opts.overwrite || false |
| var result = {} |
| |
| var isbuffer = isBuffer(target) |
| if (isbuffer || Object.prototype.toString.call(target) !== '[object Object]') { |
| return target |
| } |
| |
| // safely ensure that the key is |
| // an integer. |
| function getkey (key) { |
| var parsedKey = Number(key) |
| |
| return ( |
| isNaN(parsedKey) || |
| key.indexOf('.') !== -1 || |
| opts.object |
| ) ? key |
| : parsedKey |
| } |
| |
| var sortedKeys = Object.keys(target).sort(function (keyA, keyB) { |
| return keyA.length - keyB.length |
| }) |
| |
| sortedKeys.forEach(function (key) { |
| var split = key.split(delimiter) |
| var key1 = getkey(split.shift()) |
| var key2 = getkey(split[0]) |
| var recipient = result |
| |
| while (key2 !== undefined) { |
| var type = Object.prototype.toString.call(recipient[key1]) |
| var isobject = ( |
| type === '[object Object]' || |
| type === '[object Array]' |
| ) |
| |
| // do not write over falsey, non-undefined values if overwrite is false |
| if (!overwrite && !isobject && typeof recipient[key1] !== 'undefined') { |
| return |
| } |
| |
| if ((overwrite && !isobject) || (!overwrite && recipient[key1] == null)) { |
| recipient[key1] = ( |
| typeof key2 === 'number' && |
| !opts.object ? [] : {} |
| ) |
| } |
| |
| recipient = recipient[key1] |
| if (split.length > 0) { |
| key1 = getkey(split.shift()) |
| key2 = getkey(split[0]) |
| } |
| } |
| |
| // unflatten again for 'messy objects' |
| recipient[key1] = unflatten(target[key], opts) |
| }) |
| |
| return result |
| } |