You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
module.exports = flatten flatten.flatten = flatten flatten.unflatten = unflatten
function isBuffer (obj) { return obj && obj.constructor && (typeof obj.constructor.isBuffer === 'function') && obj.constructor.isBuffer(obj) }
function keyIdentity (key) { return key }
function flatten (target, opts) { opts = opts || {}
const delimiter = opts.delimiter || '.' const maxDepth = opts.maxDepth const transformKey = opts.transformKey || keyIdentity const output = {}
function step (object, prev, currentDepth) { currentDepth = currentDepth || 1 Object.keys(object).forEach(function (key) { const value = object[key] const isarray = opts.safe && Array.isArray(value) const type = Object.prototype.toString.call(value) const isbuffer = isBuffer(value) const isobject = ( type === '[object Object]' || type === '[object Array]' )
const newKey = prev ? prev + delimiter + transformKey(key) : transformKey(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 || {}
const delimiter = opts.delimiter || '.' const overwrite = opts.overwrite || false const transformKey = opts.transformKey || keyIdentity const result = {}
const 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) { const parsedKey = Number(key)
return ( isNaN(parsedKey) || key.indexOf('.') !== -1 || opts.object ) ? key : parsedKey }
function addKeys (keyPrefix, recipient, target) { return Object.keys(target).reduce(function (result, key) { result[keyPrefix + delimiter + key] = target[key]
return result }, recipient) }
function isEmpty (val) { const type = Object.prototype.toString.call(val) const isArray = type === '[object Array]' const isObject = type === '[object Object]'
if (!val) { return true } else if (isArray) { return !val.length } else if (isObject) { return !Object.keys(val).length } }
target = Object.keys(target).reduce(function (result, key) { const type = Object.prototype.toString.call(target[key]) const isObject = (type === '[object Object]' || type === '[object Array]') if (!isObject || isEmpty(target[key])) { result[key] = target[key] return result } else { return addKeys( key, result, flatten(target[key], opts) ) } }, {})
Object.keys(target).forEach(function (key) { const split = key.split(delimiter).map(transformKey) let key1 = getkey(split.shift()) let key2 = getkey(split[0]) let recipient = result
while (key2 !== undefined) { if (key1 === '__proto__') { return }
const type = Object.prototype.toString.call(recipient[key1]) const 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 }
|