By GewoonJaap


2018-03-13 15:16:56 8 Comments

Recently i integrated CSGO stats in my discord bot, but today i saw that for almost every player the API sends a different json data.

Here 2 examples:

https://jsonblob.com/58688d30-26d0-11e8-b426-7b3214778399 https://jsonblob.com/52ed0c3f-26d0-11e8-b426-43058df4a5a6

My question was how to request the data properly so a win is really a win and not a kill.

 .addField('**Wins:**', `${object.playerstats.stats[5].value}`, true)
 .addField('**Time played:**', `${object.playerstats.stats[2].value}` + ' minutes', true)
 .addField('**Kills:**', `${object.playerstats.stats[0].value}`, true)
 .addField('**Deaths:**', `${object.playerstats.stats[1].value}`, true)
 .addField('**Bombs planted:**',`${object.playerstats.stats[3].value}`, true)
 .addField('**Money earned:**',`${object.playerstats.stats[7].value}`, true)
 .addField('**Knife kills:**',`${object.playerstats.stats[9].value}`, true)
 .addField('**Headshot kills:**',`${object.playerstats.stats[24].value}`, true)
 .addField('**Dominations:**',`${object.playerstats.stats[39].value}`, true)
 .addField('**Rounds played:**',`${object.playerstats.stats[44].value}`, true)

4 comments

@Joseph 2018-03-13 15:25:39

The name property of stats items appear to be unique enough to find. You can use array.find to look for the correct stat by name.

const stats = object.playerstats.stats
const totalKills = stats.find(s => s.name === 'total_kills').value
const totalDeaths = stats.find(s => s.name === 'total_deaths').value

Taking it further, you can use array.reduce to generate an object whose key is name and value is value for each item in the array. This way, you access it like an object.

const stats = object.playerstats.stats
const statsObj = stats.reduce((c, e) => (c[e.name] = e.value, c), {})

const totalKills = statsObj.total_kills
const totalDeaths = statsObj.total_deaths

@Nicolas Gehlert 2018-03-13 15:28:09

beat me to it :D the .reduce approach is pretty nice and better than the actual find, since you just loop the stats array once instead of multiple times

@Briley Hooper 2018-03-13 15:39:38

Agreed that .reduce() is preferable to .find(), but you may wish to tweak your .find() callbacks to do an equality comparison (s.name === 'total_kills', for instance) so that .find() works correctly.

@Wobow 2018-03-13 15:36:20

You are approching this problem the wrong way.

JSON is not a format that is ordered. What that means is that there is no guarantee that the JSON data will return in the same order everytime. It is not a default of the API.

There is one way you could still use your way: by sorting the 'stats' array by name. but it is a long operation and not a very good idea.

The way do to this is to do a lookup by name. For example, if you want to find the wins, you do this :

object.playerstats.stats.find(elem => elem.name === 'total_wins').value;

The find function does a lookup and returns the first element matching the predicate (elem.name === 'total_wins'). It returns null if not element matched the predicate (so be careful here).

You could do a function that returns a value for you :

findValue(statsArray, name) {
    const entry = statsArray.find(elem => elem.name === name);
    return entry ? entry.value : '?';
}

And then your code would look like this :

 ...
 .addField('**Wins:**', findValue(object.playerstats.stats, 'total_wins'), true)
 ...

The main thing here is : never assume fields in a JSON will return the same every time. Always use lookup, and not indexes (unless it is sorted).

@Nicolas Gehlert 2018-03-13 15:26:33

The stats array is just not sorted. you can use .find() to get the correct entry from the stats.

for example

const totalWins = object.playerstats.stats.find(stat => {
    return stat.name === 'total_wins';
});
.addField('**Wins:**', `${totalWins.value}`, true)

@Briley Hooper 2018-03-13 15:24:35

Rather than trying to reference the array indexes, why not convert the API response into an easier-to-parse format?

// do this once...
let playerStats = {};
object.playerstats.stats.forEach(s => playerStats[s.name] = s.value);

// ...then you can use the playerStats variable however you need:
.addField('**Kills:**', `${playerStats.total_kills}`, true)
.addField('**Wins:**', `${playerStats.total_wins}`, true)

Related Questions

Sponsored Content

16 Answered Questions

[SOLVED] Parse JSON in JavaScript?

27 Answered Questions

10 Answered Questions

[SOLVED] The "right" JSON date format

  • 2012-04-23 18:32:32
  • Kamyar Nazeri
  • 715569 View
  • 868 Score
  • 10 Answer
  • Tags:   javascript json

6 Answered Questions

[SOLVED] Why does Google prepend while(1); to their JSON responses?

13 Answered Questions

[SOLVED] What's the difference between tilde(~) and caret(^) in package.json?

  • 2014-03-12 06:02:21
  • Fizer Khan
  • 480944 View
  • 2333 Score
  • 13 Answer
  • Tags:   node.js npm

45 Answered Questions

[SOLVED] How to format a JavaScript date

20 Answered Questions

[SOLVED] What is the difference between call and apply?

10 Answered Questions

2 Answered Questions

9 Answered Questions

[SOLVED] What is the difference between Bower and npm?

  • 2013-09-05 16:53:19
  • Games Brainiac
  • 295513 View
  • 1634 Score
  • 9 Answer
  • Tags:   javascript npm bower

Sponsored Content