简体   繁体   中英

How to default to a value on non-existing json value in javascript?

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.

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.

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 (ie 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.

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

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);

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM