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.
		
		
		
		
		
			
		
			
				
					
					
						
							114 lines
						
					
					
						
							2.7 KiB
						
					
					
				
			
		
		
	
	
							114 lines
						
					
					
						
							2.7 KiB
						
					
					
				| 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) {
 | |
|       if (key1 === '__proto__') {
 | |
|         return
 | |
|       }
 | |
|       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
 | |
| }
 |