Reputation: 205
My node.js application uses numerous json values from an API. For example:
stats.player.rank
stats.player.game.coins
What I want to know is how would I default to a value of 0 when calling a json path that doesn't exist? If I do var coins = player.game.coins + player.game2.coins;
and the player has no coins in game2, I would get TypeError: Cannot read property 'coins' of undefined, since the API doesn't have the object there.
Upvotes: 0
Views: 2651
Reputation: 401
You can use Optional chaining to check if a json path exists or else give undefined. Use null coalesing ?? to provide default value if the value of the expression is null or undefined.
const json = {a:1}
const defaultval = "default value"
console.log(json?.b?.c?.d ?? defaultval)
Upvotes: 0
Reputation: 9988
var coins = (player.game && player.game.coins) ? player.game.coins : 0;
var coins2 = ((player.game2 && player.game.coins)) ? player.game2.coins : 0;
var totalCoint = coins + coins2;
My suggestion is to change the api and return a list of the player's game. In this way you can use reduce to get all the coins of the player and it's a better structured data.
{
player:
{
games:
[
{
coins: 3
},
{
coins: 5
}
]
}
}
var totalCoins = player.games.reduce(function(accumulator, currentValue, currentIndex, array) {
return accumulator + currentValue;
}, 0);
Upvotes: 0
Reputation: 853
It might be possible to use a ternany operatior to achieve this
//var coins = player.game.coins + player.game2.coins
//Since you usually map your json to a certar kind of object we will create an object for testing purposes
var player = {
game: {
coins: 10
}
};
console.log(player);
console.log(player.game.coins);
//We use a ternary operator to achieve the test and set a default value
var coins = player.game.coins + (player.game2 ? player.game2.coins : 0)
console.log(coins);
EDIT: Ternary operators work as follows
It will return something or execute something, in your case you will get a return value. It has a structure as follows
var myReturnVal = test ? ifTrueDoThis: elseDoThis
You could also have nested ternary operators. For further information check this Microsoft reference
For your case we test the existance of player.game2, If it doesn´t exist, we return a 0. If it does we try and return the value of player.game2.coins
Upvotes: 0
Reputation: 1977
You can use logical operators &&
and ||
to accomplish this.
var coins = player.game.coins +
((player.game2 && player.game2.coins) || 0);
If player
may be undefined then you will need to check to ensure that exists before checking game2
. So it'd be ((player && player.game2 && player.game2.coins) || 0)
It makes sense once you realize how the code is evaluated. &&
is the AND operation and so it checks that each value exists from left to right. player
exists AND player.game2
exists AND player.game2.coins
exists and thus stops the comparison and the value is used. If either of those fail then it goes outside the parenthesis and does the OR which returns 0
for a default value.
Upvotes: 2
Reputation: 2455
There are a number of ways you could accomplish this. You can use try/catch blocks to try and set the value, if/else statements, or a ternary operator.
try/catch with default
var coins = 0
try {
coins = player.game2.coins
} catch(e) {
// Error because player or game2 doesn't exist / is null
}
if statement with default
var coins = 0
if (player && player.game2 && player.game2.coins) {
coins = player.game2.coins
}
ternary
var coins = (player && player.game2 && player.game2.coins) ? player.game2.coins : 0
You can get fancy with type checking if needed (i.e. confirm player.game2 is an object, typeof player.game2 === 'object'
, but it might be overkill if this should always either be null or an object.
Upvotes: 0