Giter Club home page Giter Club logo

flat's Introduction

flat Build Status

Take a nested Javascript object and flatten it, or unflatten an object with delimited keys.

Installation

$ npm install flat

Methods

flatten(original, options)

Flattens the object - it'll return an object one level deep, regardless of how nested the original object was:

import { flatten } from 'flat'

flatten({
    key1: {
        keyA: 'valueI'
    },
    key2: {
        keyB: 'valueII'
    },
    key3: { a: { b: { c: 2 } } }
})

// {
//   'key1.keyA': 'valueI',
//   'key2.keyB': 'valueII',
//   'key3.a.b.c': 2
// }

unflatten(original, options)

Flattening is reversible too, you can call unflatten on an object:

import { unflatten } from 'flat'

unflatten({
    'three.levels.deep': 42,
    'three.levels': {
        nested: true
    }
})

// {
//     three: {
//         levels: {
//             deep: 42,
//             nested: true
//         }
//     }
// }

Options

delimiter

Use a custom delimiter for (un)flattening your objects, instead of ..

safe

When enabled, both flat and unflatten will preserve arrays and their contents. This is disabled by default.

import { flatten } from 'flat'

flatten({
    this: [
        { contains: 'arrays' },
        { preserving: {
              them: 'for you'
        }}
    ]
}, {
    safe: true
})

// {
//     'this': [
//         { contains: 'arrays' },
//         { preserving: {
//             them: 'for you'
//         }}
//     ]
// }

object

When enabled, arrays will not be created automatically when calling unflatten, like so:

unflatten({
    'hello.you.0': 'ipsum',
    'hello.you.1': 'lorem',
    'hello.other.world': 'foo'
}, { object: true })

// hello: {
//     you: {
//         0: 'ipsum',
//         1: 'lorem',
//     },
//     other: { world: 'foo' }
// }

overwrite

When enabled, existing keys in the unflattened object may be overwritten if they cannot hold a newly encountered nested value:

unflatten({
    'TRAVIS': 'true',
    'TRAVIS.DIR': '/home/travis/build/kvz/environmental'
}, { overwrite: true })

// TRAVIS: {
//     DIR: '/home/travis/build/kvz/environmental'
// }

Without overwrite set to true, the TRAVIS key would already have been set to a string, thus could not accept the nested DIR element.

This only makes sense on ordered arrays, and since we're overwriting data, should be used with care.

maxDepth

Maximum number of nested objects to flatten.

import { flatten } from 'flat'

flatten({
    key1: {
        keyA: 'valueI'
    },
    key2: {
        keyB: 'valueII'
    },
    key3: { a: { b: { c: 2 } } }
}, { maxDepth: 2 })

// {
//   'key1.keyA': 'valueI',
//   'key2.keyB': 'valueII',
//   'key3.a': { b: { c: 2 } }
// }

transformKey

Transform each part of a flat key before and after flattening.

import { flatten, unflatten } from 'flat'

flatten({
    key1: {
        keyA: 'valueI'
    },
    key2: {
        keyB: 'valueII'
    },
    key3: { a: { b: { c: 2 } } }
}, {
    transformKey: function(key){
      return '__' + key + '__';
    }
})

// {
//   '__key1__.__keyA__': 'valueI',
//   '__key2__.__keyB__': 'valueII',
//   '__key3__.__a__.__b__.__c__': 2
// }

unflatten({
      '__key1__.__keyA__': 'valueI',
      '__key2__.__keyB__': 'valueII',
      '__key3__.__a__.__b__.__c__': 2
}, {
    transformKey: function(key){
      return key.substring(2, key.length - 2)
    }
})

// {
//     key1: {
//         keyA: 'valueI'
//     },
//     key2: {
//         keyB: 'valueII'
//     },
//     key3: { a: { b: { c: 2 } } }
// }

Command Line Usage

flat is also available as a command line tool. You can run it with npx:

npx flat foo.json

Or install the flat command globally:

npm i -g flat && flat foo.json

Accepts a filename as an argument:

flat foo.json

Also accepts JSON on stdin:

cat foo.json | flat

flat's People

Contributors

43081j avatar andornaut avatar bendrucker avatar deividfortuna avatar dependabot[bot] avatar ericchaves avatar hughsk avatar jdrouet avatar joekarow avatar jonkoops avatar kapetan avatar kvz avatar lenchvolodymyr avatar lipp avatar matthiaskunnen avatar mwleeds avatar nick-pape avatar pdehaan avatar reggino avatar resistdesign avatar silverwind avatar simonratner avatar sugarshin avatar timoxley avatar zeke avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flat's Issues

Maximum call stack size exceeded

i tried to use flatten on the data retrieved from the database
but recieved this error

Unhandled rejection RangeError: Maximum call stack size exceeded
at new Boolean (native)
at Boolean.toString (native)
at /opt/lampp/htdocs/node-fropper/node_modules/flat/index.js:17:44
at Array.forEach (native)
at step (/opt/lampp/htdocs/node-fropper/node_modules/flat/index.js:14:25)
at /opt/lampp/htdocs/node-fropper/node_modules/flat/index.js:34:16
at Array.forEach (native)
at step (/opt/lampp/htdocs/node-fropper/node_modules/flat/index.js:14:25)
at /opt/lampp/htdocs/node-fropper/node_modules/flat/index.js:34:16
at Array.forEach (native)
at step (/opt/lampp/htdocs/node-fropper/node_modules/flat/index.js:14:25)
at /opt/lampp/htdocs/node-fropper/node_modules/flat/index.js:34:16
at Array.forEach (native)
at step (/opt/lampp/htdocs/node-fropper/node_modules/flat/index.js:14:25)
at /opt/lampp/htdocs/node-fropper/node_modules/flat/index.js:34:16
at Array.forEach (native)

full error looks like this

Does unflatten enter into infinite recursion on function or array members?

I'm using this library in an F# project (transpiles to JS through using Fable). So unfortunately I have no JS repro (I'm not a JS dev).

unflatten is mostly working fine, but it seems to enter into infinite recursion on some objects. This happens even when there is seemingly nothing to unflatten.

I have an array of key-value pairs (React props) that I'm converting into an object, and then I'm using unflatten on this object.

This works fine for some prop arrays, such as this:

image

However, for others, such as this, it enters into an infinite recursion:

image

image

As you can see, in both cases, the original prop list (and thus the object) does not contain keys with the delimiter, and there are no sub-objects to recurse into (unless it does something with the function), so AFAIK unflatten shouldn't modify anything.

I have tried safe without any effect.

The weird thing is, the stack trace seems to come from the flatten function, which I do not call:

image

unflatten bug?

Hi,

I love your module, I've found many usecases for it already but now I've stumbled up what looks like a bug.

When I try to run this code:

lowerEnv =
  travis          : "true",
  travis_build_dir: "/home/travis/build/kvz/environmental",

nested = unflatten lowerEnv,
  object   : true
  delimiter: "_"

I get the following trace:

  5) Environmental config should be able handle travis environment:
     TypeError: Cannot set property 'dir' of undefined
    at /Users/kevin/workspace/environmental/node_modules/flat/index.js:83:21
    at Array.forEach (native)
    at unflatten (/Users/kevin/workspace/environmental/node_modules/flat/index.js:61:23)
    at Function.Environmental.config (/Users/kevin/workspace/environmental/src/environmental.coffee:29:14)
    at Context.<anonymous> (/Users/kevin/workspace/environmental/test/test-environmental.coffee:40:49)
    at Test.Runnable.run (/Users/kevin/workspace/environmental/node_modules/mocha/lib/runnable.js:196:15)
    at Runner.runTest (/Users/kevin/workspace/environmental/node_modules/mocha/lib/runner.js:374:10)
    at /Users/kevin/workspace/environmental/node_modules/mocha/lib/runner.js:452:12
    at next (/Users/kevin/workspace/environmental/node_modules/mocha/lib/runner.js:299:14)
    at /Users/kevin/workspace/environmental/node_modules/mocha/lib/runner.js:309:7
    at next (/Users/kevin/workspace/environmental/node_modules/mocha/lib/runner.js:247:23)
    at Object._onImmediate (/Users/kevin/workspace/environmental/node_modules/mocha/lib/runner.js:276:5)
    at processImmediate [as _immediateCallback] (timers.js:330:15)

My versions:

$ cat package.json |grep flat
    "flat": "1.2.1",
$ node --version
v0.10.22

Not sure if you're into coffeescript so I'll add the js snippet too:

var lowerEnv, nested;

lowerEnv = {
  travis: "true",
  travis_build_dir: "/home/travis/build/kvz/environmental"
};

nested = unflatten(lowerEnv, {
  object: true,
  delimiter: "_"
});

unflatten object with number as key replaces object with an array of n number length

I have a use case where i always have to unflatten a json object and i dont know if that object is already unflattened. If there is a number for an object key unflatten method create and array which replaces the original object and the array length matches the number plus one. With the last element being the element originally stored by the key. This happens only for nest objects not root level.

example:

flat.unflatten({ testing: { 12: 12 }}) => { testing: [,,,,,,,,,,,,12]}

Unflatten into arrays?

Hi!

Great work on flat. I do have a question though: would it be possible to unflatten something back into a 'real' array? E.g.

{ "a": ["foo", "bar"] }

Now becomes

{ "a.0": "foo", "a.1": "bar"}

And that is great! But when using unflatten to reverse this, we get:

{"a":{"0":"foo","1":"bar"}}

Would it be possible to unflatten back into arrays instead of regular objects when numeric keys are found in the object?

.flatten doesn't preserve empty objects.

console.log(flat.flatten({
  has: {
    value : 'someValue'
  },
  empty : {
    value : {
      nested: { }
    }
  }
}));

will return

{ 'has.value': 'someValue' }

instead the expected:

{ 'has.value': 'someValue', 'empty.value.nested': { } }

Edit:

To elaborate. It might seem as objects imply nesting, but if we don't account for empty objects, flatteining then deflattening an object will not preserve the original object structure.

In this example, doing flat.unflatten(flat.flatten(o)) will not retain the 'empty.value.nested' tree.

CLI

Hi, @hughsk 👋

Just thinking it would be cool to be able to npx flat some.json

maxDepth only working on first element

Hey everyone,

It appears that when using maxDepth, only the first key value is being properly flattened. You can easily see this behaviour if you update the customDepth test to:

flatten({
  hello: {
    world: {
      again: 'good morning'
    }
  },
  lorem: {
    ipsum: {
      dolor: 'good evening'
    }
  }
}, {
  maxDepth: 2
})

Instead of the expected result:

{
  'hello.world': {
    again: 'good morning'
  },
  'lorem.ipsum': {
    dolor: 'good evening'
  }
}

You instead receive:

{
  'hello.world': { 
    again: 'good morning'
  },
  lorem: {
    ipsum: {
      dolor: 'good evening'
    }
  }
}

The issue appears to be that the currentDepth variable is only incremented, and never reset or decremented.

I have created a pull request #47 to remedy the situation.

Major rewrite in progress

I'm doing a major rewrite using ES6 on this flat#dev branch

The current implementation was getting out of hand and full of "garbage" to make it very difficult to make sense of. Let me know if you want to help out in this effort.
I'm planning to use flat in my json-operator

It seems like flat is too eager to make arrays.

Hi, first of all thanks a lot for making flat, it's exactly what I was looking for.

I think I might have found an issue. When being passed this object:

{ filename: '/Users/kevin/metriks/rrds/nslookup/kvz-imac-home-4.local-nslookup.rrd',
     rrd_version: '0003',
     step: 300,
     last_update: 1392592863,
     header_size: 1832,
     'ds.8_8_8_8.index': 0,
     'ds.8_8_8_8.type': 'GAUGE',
     'ds.8_8_8_8.minimal_heartbeat': 600,
     'ds.8_8_8_8.min': 'NaN',
     'ds.8_8_8_8.max': 'NaN',
     'ds.8_8_8_8.last_ds': '19',
     'ds.8_8_8_8.value': 209,
     'ds.8_8_8_8.unknown_sec': 52,
     'ds.8_8_4_4.index': 1,
     'ds.8_8_4_4.type': 'GAUGE',
     'ds.8_8_4_4.minimal_heartbeat': 600,
     'ds.8_8_4_4.min': 'NaN',
     'ds.8_8_4_4.max': 'NaN',
     'ds.8_8_4_4.last_ds': '20',
     'ds.8_8_4_4.value': 220,
     'ds.8_8_4_4.unknown_sec': 52,
     'ds.4_2_2_2.index': 2,
     'ds.4_2_2_2.type': 'GAUGE',
     'ds.4_2_2_2.minimal_heartbeat': 600,
     'ds.4_2_2_2.min': 'NaN',
     'ds.4_2_2_2.max': 'NaN',
     'ds.4_2_2_2.last_ds': '122',
     'ds.4_2_2_2.value': 1342,
     'ds.4_2_2_2.unknown_sec': 52,
     'ds.208_67_222_222.index': 3,
     'ds.208_67_222_222.type': 'GAUGE',
     'ds.208_67_222_222.minimal_heartbeat': 600,
     'ds.208_67_222_222.min': 'NaN',
     'ds.208_67_222_222.max': 'NaN',
     'ds.208_67_222_222.last_ds': '18',
     'ds.208_67_222_222.value': 198,
     'ds.208_67_222_222.unknown_sec': 52,
     'ds.172_16_0_23.index': 4,
     'ds.172_16_0_23.type': 'GAUGE',
     'ds.172_16_0_23.minimal_heartbeat': 600,
     'ds.172_16_0_23.min': 'NaN',
     'ds.172_16_0_23.max': 'NaN',
     'ds.172_16_0_23.last_ds': '-1',
     'ds.172_16_0_23.value': -11,
     'ds.172_16_0_23.unknown_sec': 52,
     'rra.0.cf': 'AVERAGE',
     'rra.0.rows': 300,
     'rra.0.cur_row': 215,
     'rra.0.pdp_per_row': 1,
     'rra.0.xff': 0.5,
     'rra.0.cdp_prep.0.value': 'NaN',
     'rra.0.cdp_prep.0.unknown_datapoints': 0,
     'rra.0.cdp_prep.1.value': 'NaN',
     'rra.0.cdp_prep.1.unknown_datapoints': 0,
     'rra.0.cdp_prep.2.value': 'NaN',
     'rra.0.cdp_prep.2.unknown_datapoints': 0,
     'rra.0.cdp_prep.3.value': 'NaN',
     'rra.0.cdp_prep.3.unknown_datapoints': 0,
     'rra.0.cdp_prep.4.value': 'NaN',
     'rra.0.cdp_prep.4.unknown_datapoints': 0,
     '': '' }

The resulting unflattened structure looks like this:

{ filename: '/Users/kevin/metriks/rrds/nslookup/kvz-imac-home-4.local-nslookup.rrd',
     rrd_version: '0003',
     step: 300,
     last_update: 1392592863,
     header_size: 1832,
     ds:
      [ ,
        ,
        ,
        ,
        [Object],
        ,
        ,
        ,
        [Object],
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        [Object],
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        ,
        [Object] ],
     rra: [ [Object] ],
     '': '' }

My guess is that flat too eagerly tries to look for numbers in keys as it wants to forge arrays for those.

Let me know if I'm overlooking something.

Best,
Kevin

{object: true} should be the default

IMHO, {object: true} should be the default. I spent some time trying to figure out why I had an array containing 8004 * null... I way simply flattening an object containing this key: messages.upsells.errors.8005

Thanks for the good work!

Blank array not flattened!

I'm using flat module for preparing object to store data in Redis DB. (Redis doesn't allow array and nested object )
Now, the Issue is Flat doesn't do anything to blank array.
E.g.

{
    a: [],
    a1: {
        a11: 1
    }
    b: 'test',
    c: 12
}
is flatten to 
{
    a: [],
    a1.a11: 1,
    b: "test",
    c: 12,
}

this gives me error on Redis. Can Flat module help me with this?

Almost a one-liner with ES6

Hey @hughsk

We are using your flat module at Echo. Thanks a lot for the amazing work!

I got a bit inspired today to try to make the flatten function as a one-liner. Have a look below:

const flatten = (c, d = '.') => {
  const r = {};
  (function f(o, p) {
      Object.keys(o).forEach(k => (o[k] && typeof o[k] === 'object' ? f(o[k], p ? `${p}${d}${k}` : k) : (r[p ? `${p}${d}${k}` : k] = o[k])));
  }(c));
  return r;
};

Tests:

  it('flatten', () => {
    let $in = { a: 1, b: { c: 2, d: 2, e: { f: 3, g: 3, h: 3, j: { k: { l: true } } } } };
    let $out = { a: 1, 'b.c': 2, 'b.d': 2, 'b.e.f': 3, 'b.e.g': 3, 'b.e.h': 3, 'b.e.j.k.l': true };
    expect(flatten($in)).to.deep.equal($out);

    $in = ['a', { b: 1 }, { c: 2, d: 2 }];
    $out = { 0: 'a', '1.b': 1, '2.c': 2, '2.d': 2 };
    expect(flatten($in)).to.deep.equal($out);

    $in = { a: { b: 1, c: 1 } };
    $out = { 'a/b': 1, 'a/c': 1 };
    expect(flatten($in, '/')).to.deep.equal($out);

    $in = { x: 1, y: null, z: undefined };
    $out = { x: 1, y: null, z: undefined };
    expect(flatten($in)).to.deep.equal($out);
  });

Original code here https://github.com/RomansBermans/transformer

Universal support

Now flatjs suggests, that it uses in nodejs. But would be pretty if you check AMD and browser too.

Conversion Problem

It may just be me doing something stupid however I'm converting the following:

{ app_preferences: { test: 1 }, settings: { network: { appnetwork: { device: '/dev/eth1' }, devnetwork: { device: '/dev/eth0' } } } }

The object flatten is producing is this:

{"0":123,"1":10,"2":32,"3":110,"4":100,"5":109,"6":95,"7":112,"8":114,"9":101,"10":102,"11":101,"12":114,"13":101,"14":110,"15":99,"16":101,"17":115,"18":58,"19":32,"20":123,"21":10,"22":32,"23":32,"24":32,"25":116,"26":101,"27":115,"28":116,"29":58,"30":32,"31":49,"32":10,"33":32,"34":125,"35":44,"36":10,"37":32,"38":115,"39":101,"40":116,"41":116,"42":105,"43":110,"44":103,"45":115,"46":58,"47":32,"48":123,"49":10,"50":32,"51":32,"52":32,"53":110,"54":101,"55":116,"56":119,"57":111,"58":114,"59":107,"60":58,"61":32,"62":123,"63":10,"64":32,"65":32,"66":32,"67":32,"68":32,"69":110,"70":100,"71":109,"72":110,"73":101,"74":116,"75":119,"76":111,"77":114,"78":107,"79":58,"80":32,"81":123,"82":10,"83":32,"84":32,"85":32,"86":32,"87":32,"88":32,"89":32,"90":100,"91":101,"92":118,"93":105,"94":99,"95":101,"96":58,"97":32,"98":39,"99":47,"100":100,"101":101,"102":118,"103":47,"104":101,"105":116,"106":104,"107":49,"108":39,"109":10,"110":32,"111":32,"112":32,"113":32,"114":32,"115":125,"116":44,"117":10,"118":32,"119":32,"120":32,"121":32,"122":32,"123":111,"124":116,"125":97,"126":110,"127":101,"128":116,"129":119,"130":111,"131":114,"132":107,"133":58,"134":32,"135":123,"136":10,"137":32,"138":32,"139":32,"140":32,"141":32,"142":32,"143":32,"144":100,"145":101,"146":118,"147":105,"148":99,"149":101,"150":58,"151":32,"152":39,"153":47,"154":100,"155":101,"156":118,"157":47,"158":101,"159":116,"160":104,"161":48,"162":39,"163":10,"164":32,"165":32,"166":32,"167":32,"168":32,"169":125,"170":10,"171":32,"172":32,"173":32,"174":125,"175":10,"176":32,"177":125,"178":10,"179":125,"180":10,"181":10}

Code being used:

`
const fs = require('fs');

var flatten = require('flat');

var loadconfig = fs.readFileSync('config.json');

var config_params = flatten(loadconfig);

console.log("%j", config_params);

`

how to exclude the values

How to exclude unflattening the values of the key?

    'files.exclude': {
        default: { '**/.git': true, '**/.svn': true, '**/.hg': true, '**/CVS': true, '**/.DS_Store': true },
  }

Output:

  { files: {
     exclude: {
      "default": Object {
        "**/": Object {
          "DS_Store": true,
          "git": true,
          "hg": true,
          "svn": true,
        },
        "**/CVS": true,
      }
 }
} 

Expectation

{ files: { exclude: { default: { '**/.git': true, '**/.svn': true, '**/.hg': true, '**/CVS': true, '**/.DS_Store': true }}}}

heap out of memory

<--- Last few GCs --->

[4742:0x110000000] 13658 ms: Mark-sweep 1388.1 (1425.4) -> 1387.6 (1425.4) MB, 94.9 / 0.0 ms (average mu = 0.144, current mu = 0.047) allocation failure GC in old space requested
[4742:0x110000000] 13907 ms: Mark-sweep 1387.6 (1425.4) -> 1387.6 (1425.9) MB, 233.0 / 0.0 ms (average mu = 0.095, current mu = 0.062) allocation failure GC in old space requested

<--- JS stacktrace --->

==== JS stack trace =========================================

0: ExitFrame [pc: 0x1fd429adbe3d]

Security context: 0x350268d1e6e9
1: step [0x350214a022c9] [/Volumes/Root/Users/Elvis/Desktop/buybuybuy/project/packages/LoginService/node_modules/flat/index.js:~14] [pc=0x1fd42a19fcef](this=0x35020a88d461 ,object=0x350214a18891 <JSArray[15]>,prev=0x3502c1782229 <Very long string[3614]>,currentDepth=400)
2: step [0x350214a022c9] [/Volumes/Root/Users/Elvis/Desktop/buy...

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
1: 0x10003cf99 node::Abort() [/usr/local/bin/node]
2: 0x10003d1a3 node::OnFatalError(char const*, char const*) [/usr/local/bin/node]
3: 0x1001b7835 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node]
4: 0x100585682 v8::internal::Heap::FatalProcessOutOfMemory(char const*) [/usr/local/bin/node]
5: 0x100588155 v8::internal::Heap::CheckIneffectiveMarkCompact(unsigned long, double) [/usr/local/bin/node]
6: 0x100583fff v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [/usr/local/bin/node]
7: 0x1005821d4 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/usr/local/bin/node]
8: 0x10058ea6c v8::internal::Heap::AllocateRawWithLigthRetry(int, v8::internal::AllocationSpace, v8::internal::AllocationAlignment) [/usr/local/bin/node]
9: 0x10058eaef v8::internal::Heap::AllocateRawWithRetryOrFail(int, v8::internal::AllocationSpace, v8::internal::AllocationAlignment) [/usr/local/bin/node]
10: 0x100573d8e v8::internal::Handlev8::internal::String v8::internal::Factory::AllocateInternalizedStringImpl<true, v8::internal::Handlev8::internal::String >(v8::internal::Handlev8::internal::String, int, unsigned int) [/usr/local/bin/node]
11: 0x1006d7ae5 v8::internal::InternalizedStringKey::AsHandle(v8::internal::Isolate*) [/usr/local/bin/node]
12: 0x1006c0a90 v8::internal::StringTable::AddKeyNoResize(v8::internal::Isolate*, v8::internal::StringTableKey*) [/usr/local/bin/node]
13: 0x1006c0430 v8::internal::StringTable::LookupString(v8::internal::Isolate*, v8::internal::Handlev8::internal::String) [/usr/local/bin/node]
14: 0x100240d50 v8::internal::LookupIterator::LookupIterator(v8::internal::Handlev8::internal::Object, v8::internal::Handlev8::internal::Name, v8::internal::LookupIterator::Configuration) [/usr/local/bin/node]
15: 0x100675ce5 v8::internal::LookupIterator::PropertyOrElement(v8::internal::Isolate*, v8::internal::Handlev8::internal::Object, v8::internal::Handlev8::internal::Object, bool*, v8::internal::LookupIterator::Configuration) [/usr/local/bin/node]
16: 0x100803fd3 v8::internal::Runtime::SetObjectProperty(v8::internal::Isolate*, v8::internal::Handlev8::internal::Object, v8::internal::Handlev8::internal::Object, v8::internal::Handlev8::internal::Object, v8::internal::LanguageMode) [/usr/local/bin/node]
17: 0x100807863 v8::internal::Runtime_SetProperty(int, v8::internal::Object**, v8::internal::Isolate*) [/usr/local/bin/node]
18: 0x1fd429adbe3d
19: 0x1fd42a19fcef

Deeply Nested Array Being Coerced Into Object

hi there,

I've come across what I believe is a bug. I start with an object that has an array of strings nested a couple levels from the top (the attachments array).

But, once I flatten the object and save it in MongoDB, the result is that the customers[0].names[0].attachments array has been coerced into an object for some reason:

BEFORE

{
  _id : 1234567890,
  customers : [
    {
      names : [
        {
          type : 'legal',
          value : 'John Smith',
          attachments : [
            'abcdefg-12345'
          ]
        }
      ]
    }
  ]
}

AFTER

{
  _id : 1234567890,
  customers : [
    {
      names : [
        {
          type : 'legal',
          value : 'John Smith',
          attachments : {
            "0" : 'abcdefg-12345'
          }
        }
      ]
    }
  ]
}

Is this the expected behaviour of flat?

Flatten starting at a specific level

Hello,

First thanks for such a great library!

I was wondering if there is a config that will allow me to flatten my JSON file starting at a specific depth instead of always flattening from the root to leaf.

Use case:

Input:

flatten(
  {
    "foo": {
      "bar": {
        "a": 1,
        "b": 2,
        "c": 3
      }
    },
    "amaze": {
      "muppet": "wow",
      "haw": "maw"
    }
  }
);

Output:

{
  "foo": {
    "bar.a": 1,
    "bar.b": 2,
    "bar.c": 3,
  },
  "amaze": {
    "muppet": "wow",
    "haw": "maw"
  }
}

Looking at the current options it seems like this would be the opposite of maxDepth. Maybe a minDepth option.

Possible to allow key's with '.'s in them?

I'm looking for a way to preserve keys that have .s in to use the same syntax as lodash's set/get.

Ideally something like this:

// Input
{
  some: {
    'key.with.dots': value
  }
}

// Output
{
  some['key.with.dots']: value
}

The problem I've found with using the transformKey option is they still get the . joining them.

I have this:

const flatData = flatten(data, {
  transformKey: key => (key.includes('.') ? `['${key}']` : key),
});

But the output looks like this. (extra . after some)

{
  some.['key.with.dots']: value
}

I've worked around the issue for now by looping through the flattend data and doing a string replace on .[ with [.

const fixedData = Object.entries(flatData).reduce((acc, [key, value]) => {
  const newKey = key.includes('.[') ? key.replace('.[', '[') : key;
  acc[newKey] = value;
  return acc;
}, {});

Custom delimiter function

Proposal

Support passing (string, string) => string function as a delimiter option.

For example, for object:

{
  first: {
    second: "hello"
  }
}

and delimiter:

(left, right) => left + right.charAt(0).toUpperCase() + right.slice(1);

it will produce camel case names:

{
  firstSecond: "hello"
}

Changelog or release notes

You really should add a changelog file or at least release notes on the releases tab in GitHub to communicate your changes to everyone.

Arrow function breaks in IE.

A single arrow function is breaking functionality in < IE11.

target = Object.keys(target).reduce((result, key) =>

I am using this module in the browser for a angular/typescript app.

Flatten arrays to string

Hi, I have a unique use-case, I am currently building a dynamic table based on an object's keys. So this does not work correctly when the object has an array associated with it. Would it be possible to add an additional parameter to specify that arrays should be strings with the safe option associated?

for example:
`flatten({
title:'Hello world',
countries: ['ZAF','USA','GRL']
}, {
safe:true,
arraytostring:true
});

//output:
// {
// title:'Hello World',
// countries: '["ZAF","USA","GRL"]'
`

If you do not want to add this functionality to your repo, can I clone the project and add this for my specific use-case?

Flatten does not flatten empty objects or arrays

Issue:

Suppose I have the following object

{ "foo": { "bar": "hello-world" }, "data": {}, "tests": [] }

I would expect this object to be flattened if I need it for some sort of operation which does not support complex objects.
Perhaps it would be flattened in this way
{ "foo.bar": "hello-world", "data": "{}", "tests": "[]" }

Or, perhaps there is a better way to do this; but, what actually occurs is the following

{ "foo.bar": "hello-world", "data": {}, "tests": [] }

Where, in reality, this has not been flattened. There still exists nested objects, they are just empty.

Supported char sets

What character sets are supported? Seems to abort with words like "apéritif"

Who is down for a minDepth option?

This would complement maxDepth in a coherent way.

minDepth

Number of nested objects to skip before flattening others.

var flatten = require('flat')

flatten({
    key1: {
        keyA: 'valueI'
    },
    key2: {
        keyB: 'valueII'
    },
    key3: { a: { b: { c: 2 } } }
}, { minDepth: 1 })

// {
//   key1: { keyA: 'valueI' },
//   key2: { keyB: 'valueII' },
//   key3: { a: { 'b.c': 2 } }
// }

TypeError with unflatten when destination property is null

// ok
flat.unflatten({ 'a.b': 'c' }); // { a: { b: 'c' } }
// not ok
flat.unflatten({ a: null, 'a.b': 'c' }); // TypeError: Cannot set property 'b' of null

Probably, it happens because of 'object' === typeof null, but I didn't see the source

Missing license

If possible, can you please add a LICENSE file, or place the BSD license in the README? Thank you!

Feature request: Flatten __proto__

const a = {
  __proto__: {
    fun: () => 'foo',
    __proto__: {
      fun: () => 'bar',
    },
  },
};

Should flatten to

const a = {
  '__proto__.fun': () => 'foo',
  '__proto__.__proto__.fun': () => 'bar',
};

We can have a flag like extraKeys: ['__proto__']

Object turns into an array after unflattening

var flat = require("flat");

var data  = {
  "object": {"0": "a", "1": "b"}
};

console.log(flat.unflatten(flat.flatten(data)));

Outputs

{ object: [ 'a', 'b' ] }

Not sure how often people would use integers as object keys, but is a valid case nonetheless.

I realize that yes, you can pass {object:true} to unflatten, and it will not automatically assume it's an array, but then you get the opposite behavior. i.e. "Arrays turn into objects".

A more generic solution would be to use square brackets in the flattened format, where:

object[0], and object.0 imply different data structures.

Array unflatten isn't correct

var flat = require('flat')

var obj = [{a: 1}, {b: 2}]
var _obj = flat.flatten(obj)
console.log(_obj)// { '0.a': 1, '1.b': 2 }
console.log(flat.unflatten(_obj))// { '0': { a: 1 }, '1': { b: 2 } }

I want [{a: 1}, {b: 2}], but not { '0': { a: 1 }, '1': { b: 2 } }

Unflatten not happening properly

I have tried the below code, where "c.d": 20 turns into "c: { d: 20 }". I have used {object:true} which also didnt help me.

var flatten = require('flat'),
unflatten = require('flat').unflatten;

var obj1 = flatten({a: 10, b: 15, "c.d": 20, e: 50})

var res = flatten(obj1)
console.log(res) //{ a: 10, b: 15, 'c.d': 20, e: 50 }
var fin = unflatten(res,{object: true});
console.log(fin) //{ a: 10, b: 15, c: { d: 20 }, e: 50 }

Add flat-stop-condition function

Hello Community,

Have you thought about adding a function option that could act as a flat stop condition?

I'm having issues with flattening an ObjectId (from MongoDB). Currently Flat will split this in bsonType and id (with unknown chars).

If I could pass down a function to Flat that would receive the object to process and decide if it should be processed or continue it would be great no?

What do you think?

I'm available to create a PR if you feel that this is interesting.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.