index.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. var isBuffer = require('is-buffer')
  2. module.exports = flatten
  3. flatten.flatten = flatten
  4. flatten.unflatten = unflatten
  5. function flatten (target, opts) {
  6. opts = opts || {}
  7. var delimiter = opts.delimiter || '.'
  8. var maxDepth = opts.maxDepth
  9. var output = {}
  10. function step (object, prev, currentDepth) {
  11. currentDepth = currentDepth || 1
  12. Object.keys(object).forEach(function (key) {
  13. var value = object[key]
  14. var isarray = opts.safe && Array.isArray(value)
  15. var type = Object.prototype.toString.call(value)
  16. var isbuffer = isBuffer(value)
  17. var isobject = (
  18. type === '[object Object]' ||
  19. type === '[object Array]'
  20. )
  21. var newKey = prev
  22. ? prev + delimiter + key
  23. : key
  24. if (!isarray && !isbuffer && isobject && Object.keys(value).length &&
  25. (!opts.maxDepth || currentDepth < maxDepth)) {
  26. return step(value, newKey, currentDepth + 1)
  27. }
  28. output[newKey] = value
  29. })
  30. }
  31. step(target)
  32. return output
  33. }
  34. function unflatten (target, opts) {
  35. opts = opts || {}
  36. var delimiter = opts.delimiter || '.'
  37. var overwrite = opts.overwrite || false
  38. var result = {}
  39. var isbuffer = isBuffer(target)
  40. if (isbuffer || Object.prototype.toString.call(target) !== '[object Object]') {
  41. return target
  42. }
  43. // safely ensure that the key is
  44. // an integer.
  45. function getkey (key) {
  46. var parsedKey = Number(key)
  47. return (
  48. isNaN(parsedKey) ||
  49. key.indexOf('.') !== -1 ||
  50. opts.object
  51. ) ? key
  52. : parsedKey
  53. }
  54. var sortedKeys = Object.keys(target).sort(function (keyA, keyB) {
  55. return keyA.length - keyB.length
  56. })
  57. sortedKeys.forEach(function (key) {
  58. var split = key.split(delimiter)
  59. var key1 = getkey(split.shift())
  60. var key2 = getkey(split[0])
  61. var recipient = result
  62. while (key2 !== undefined) {
  63. var type = Object.prototype.toString.call(recipient[key1])
  64. var isobject = (
  65. type === '[object Object]' ||
  66. type === '[object Array]'
  67. )
  68. // do not write over falsey, non-undefined values if overwrite is false
  69. if (!overwrite && !isobject && typeof recipient[key1] !== 'undefined') {
  70. return
  71. }
  72. if ((overwrite && !isobject) || (!overwrite && recipient[key1] == null)) {
  73. recipient[key1] = (
  74. typeof key2 === 'number' &&
  75. !opts.object ? [] : {}
  76. )
  77. }
  78. recipient = recipient[key1]
  79. if (split.length > 0) {
  80. key1 = getkey(split.shift())
  81. key2 = getkey(split[0])
  82. }
  83. }
  84. // unflatten again for 'messy objects'
  85. recipient[key1] = unflatten(target[key], opts)
  86. })
  87. return result
  88. }