79

Is there some syntax for setting properties based on a condition?

data: {
    userId: 7,
    actionId: 36,
    express: (myCondition ? true : null) // does not work
}

I want express to be either set to a value or not set at all (i.e., there should be no key named express), and without extra statements after the definition. I know I can use it as a boolean, but the receiving side is using an isset() check and I'm wondering if I can avoid modifying it.


Edit: Seems there is no direct solution to the problem as stated. Here are the close suggestions:

JSON.stringify (Chris Kessel, dystroy):

var json = JSON.stringify( {
    data: {
        userId: 7,
        actionId: 36,
        express: (myCondition ? true : null)
    }
});

An anonymous function (Paulpro):

var data = new function(){
    this.userId = 7;
    this.actionId = 36;
    myCondition && (this.express = true);
};

An extra statement (x4rf41):

data: {
    userId: 7,
    actionId: 36
}
if(myCondition) data["express"] = true;

Eval (a former colleague of mine):

eval("data = {userId: 7, actionId: 36 " + (myCondition ? ", express: true}" : "}"))

Conditional definition (don't really know how to label this one):

data = (
    (myCondition && { userId: 7, actionId: 36, express: true }) ||
    (!myCondition && { userId: 7, actionId: 36 })
);
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
mcmlxxxvi
  • 1,358
  • 1
  • 11
  • 21

7 Answers7

114

Use the spread operator.

data: {
    userId: 7,
    actionId: 36,
    ...myCondition && {express: true}
}

Note that if you're using Flow, that syntax might generate type check errors. You can write the above more explicitly, and less succinctly, as:-

data: {
    userId: 7,
    actionId: 36,
    ...(myCondition ? {express: true} : {})
}
MD. RAKIB HASAN
  • 3,670
  • 4
  • 22
  • 35
ericsoco
  • 24,913
  • 29
  • 97
  • 127
  • 5
    This is a great answer. – R. AbuBaker Nov 13 '20 at 00:10
  • if don't want empty object: ...(myCondition ? {express: true} : null) then filter null by: data = data.filter(function(x) { return x !== null }); – user1345817 Apr 17 '22 at 15:53
  • @user1345817 Just to chime in, the update you added is not needed because the spread in the answer (`...`) eliminates the empty object (`{}`) in the falsy case of the ternary. Thus, the property is only added in the truthy case. – adstwlearn Apr 29 '23 at 04:46
78

Do it like this :

data: {
    userId: 7,
    actionId: 36,
    express: (myCondition ? true : undefined)
}

A property whose value is undefined isn't written when you stringify the object to JSON.


EDIT : It appears from the comments that there is no JSON involved in fact. OP is using $.ajax so $.param is probably used. $.param, unfortunately, does create an entry for properties whose value is undefined. So there's probably no solution without any supplementary line of code.

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
9

You can do it if you define your object using an anonymous function instead of object literal notation:

var data = new function(){
    this.userId = 7;
    this.actionId = 36;
    myCondition && (this.express = true);
};

The resulting data object is the exact same, except it's constructor will be the anonymous function instead of window.Object.

Paul
  • 139,544
  • 27
  • 275
  • 264
5

first of all, thats javascript, not JSON.

the solution:

data: {
    userId: 7,
    actionId: 36
}
if(myCondition) data["express"] = true;
x4rf41
  • 5,184
  • 2
  • 22
  • 33
3

You could do something like this:

var json = JSON.stringify( {
    data: {
        userId: 7,
        actionId: 36,
        express: (myCondition ? true : null)
    }
});
Chris Kessel
  • 5,583
  • 4
  • 36
  • 55
3

The spread operator now fixes this. Here is an example with two comparisons.

Note: I changed date: to const date = so that it is valid runnable javascript. This can also be used with data: if it is supposed to be inside of a deep object structure.

const compareValue = 13;
const data =  {
    userId: 7,
    actionId: 36,
    ...(compareValue > 10 && {propertyForGreaterThan10: 'foo'}),
    ...(compareValue < 10 && {propertyForLessThan10: 'bar'}),
}
console.log(data);
RobKohr
  • 6,611
  • 7
  • 48
  • 69
2

A bit old but there is a good solution as well you can do :

data: {
    userId: 7,
    actionId: 36
}

Object.assign(data, !myCondition && { express: yourValue });

Thus it will assign your express property with the value you need if your condition is false.

Imad El Hitti
  • 917
  • 3
  • 10
  • 23