1

I am attempting to create an object from JSON.

Part of my object looks like

a: {
   name: "A name",
   b: {
      c: {
         d: []
         }
      }
   }

To save bandwidth, empty arrays and empty objects are stripped from the JSON, so the JSON that I receive is

{ "a": { "name": "A name" }}

If I just convert the JSON to an object, this leads to errors when I try to do things like a.b.c.d.length, as undefined does not have a length.

At the moment, I am populating the missing fields by something like

const json = getJson();
const obj = {
    ...json,
    a: {
       ...json.a,
       b: {
          ...json.a.b,
          c: {
             ...json.a.b.c,
             d: json.a.b.c.d || []
             }
           }
        }
     };

This is pretty verbose, and is going to get even uglier when there are several fields that need default values.

One obvious solution is to not strip out the empty arrays from the transmitted JSON. Assuming that that is not possible, is there a better way to handle this case?

In the real case, there are multiple fields at each level, so all of the spread operators are necessary. (Even if they were not, I would want to include them as the structure is likely to grow in the future.)

Edit: I am not using JQuery. I am using whatwg-fetch to retrieve data.

2
  • To be clear, this is not ES6/2015, this is a stage 3 proposal for ECMAScript Commented Jul 5, 2017 at 20:57
  • @dama I don't think that would achieve as fine-grained control as you think it will. with $.extend({a:{b:{c:'hello'}}}, {a:{d:{e:'goodbye'}}}), asker would hope for {a:{b{c:'hello'},d:{e:'goodbye'}}}, but actually just gets {a:{d:{e:'goodbye'}}} Edit my mistake, forgot about the optional first argument deep. This would work: $.extend(true, {a:{b:{c:'hello'}}}, {a:{d:{e:'goodbye'}}}) Commented Jul 5, 2017 at 21:11

3 Answers 3

2

I would suggest some sort of solution in which you establish a pre-determined schema, and continue to omit empty arrays/values. You can then do something like

_.get(object, 'property.path.here', defaultValue)

with lodash.get(), where defaultValue is determined by your schema as an empty string "", 0, null, etc.

Sign up to request clarification or add additional context in comments.

Comments

2

Removing empty objects/arrays from response is not a good practice, because these can be valid values.

It is premature optimization, which does not have real benefit on performance. In return it will give you a lot of headaches when you will need to specially handle each response.

But if you still think that it is worth, then I recommend lodash get function.

_.get(object, 'property.path.here')

Comments

0

For best practice, I think you should not employ sophisticated approach or syntax. Just use a common default value set of Javascript:

var _d = a.b.c.d || [].
// does something with _d.length

While you are trying to do something, you can achieve that but code quality is worse. Think different and do different it may be better.

Moreover, I think declare the original a object explicitly with all properties is better than remove empty property like you do.

2 Comments

I agree in general with avoiding "over-complicated" approaches, but I think it's a mistake to lump the asker's "bandwidth-saving" technique in with those bad practices. I think if the JSON is as large as he's saying, omitting empty objects and arrays is going to conserve a lot of resources in the long run, as long as they establish some sort of schema for default values.
Yes, it depends on the situation. I just open another approach rather insist on follow one way.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.