flat: 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.

About this issue

  • Original URL
  • State: open
  • Created 6 years ago
  • Reactions: 2
  • Comments: 20

Most upvoted comments

@lucas-rudd my branch is at https://github.com/aecepoglu/flat . The feature is added to flattening, but not unflattening. I have written tests for both cases; so if you can send me a PR which makes both of them pass we can be done with this.

Here’s an example case for this issue comes up: some downstream code simply does not tolerate nested objects. So the developer (me in this case) goes looking for a library/function to flatten objects and make this not happen. This library is 99% of the way there, aside from this quite surprising case where some objects sail right through, un-flattened, still containing nested objects causing downstream trouble.

Reversibility is not the only important criteria - in some use cases it is less important than “the output is always flat no matter the input”.

I have did the flattening bit but the unflatten code is a tad bit uglier so it’ll take some more time.

And still @lucas-rudd , I’m in favour of removing empty objects since they represent nothing logically. Because different people will have different behaviours in mind when they want to flatten something which can’t be flattened without being presumptuous, I want it to be the callback way.

This is clearly an edge case and people have different ways of dealing with edge cases - so why not let them?

I think we should let the user specify a callback (maybe in the options object) which is called whenever an empty key is encountered during flattening. The callback could then return a value which is assigned to the key. That way, the user is in complete control over what happens.

As a plus, we could also add default callbacks for standard stuff like: Preserve (leaves the empty object or array as the value. This already it’s default behavior ) , Remove (removes the key entirely) e.t.c.

The only problem I have with removing the key altogether is similar to what @king-kay mentioned; an empty object is a ‘truthy’ value in javascript, whereas a null value is not. So, if I were doing something like

if ( object.key )
...

Then if key is an empty object, this statement would evaluate to true. Removing it causes this to evaluate to false.

Similarly, modifying something like this

{
  'a': {
    'b': { }
  }
}

To this

{
  'a.b.': ''
}

(where the key is a dot b dot to indicate an empty object) produces the same issue mentioned above (an empty string is falsey)

Also, removing the key is irreversible, whereas modifying the value is not.