0

I'm using the code from Sorting an array of objects by property values to sort my Json. But it isn't working, I'm using request to store a Json from a web API and using jsonpath.

It isn't sorting, it's just sending me the GET content (before sort). I feel it's the problem with the parseFloat (line 15), but I am unsure how to fix it. I went into https://jsonpath.com/ to test a bit, and it should be ..rank not .rank

My code:

var request = require('request');
var jp = require('jsonpath');

var options = {
  'method': 'GET',
  'url': 'https://groups.roblox.com/v1/groups/2642914/roles',
  'headers': {
  }
};
request(options, function (error, response) {
  if (error) throw new Error(error);
  var obj = JSON.parse(response.body);
  var rolesList = jp.query(obj, '$..roles');
  rolesList.sort(function(a, b) {
    return parseFloat(a.rank) - parseFloat(b.rank);
});
    console.log(rolesList)
});
  • `isn't working` doesn't help in further debugging the problem since thats a given. Could you provide an error message or place additional `console.log`s to further narrow down the problem? – GetSet Jul 04 '20 at 03:59
  • Ahh yes. Will add that. – Ipexidex725 Jul 04 '20 at 04:01
  • When I manually fetch the JSON and hard-code it into a test example, the sorting works well. https://jsfiddle.net/xby6kr5v/1/ –  Jul 04 '20 at 04:08
  • is there a reason you're using request npm package? – user120242 Jul 04 '20 at 04:16
  • It's for my bot on Discord. – Ipexidex725 Jul 04 '20 at 04:28
  • request npm package is explicitly deprecated. They provide alternatives on their page. edit: oh it's for a bot, so you don't care about cors – user120242 Jul 04 '20 at 04:33
  • and your JSON array is wrapped in an outer array. `rolesList[0].sort(...` (due to the way you are accessing it through jsonpath) – user120242 Jul 04 '20 at 04:37
  • @user120242 "cors"? – Ipexidex725 Jul 04 '20 at 04:48
  • https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS which really only matters if you're fetching in the browser. The JSONPath you want is `$.roles.*`, or you need to use `rolesList[0]` (one or the other) to get he first match, since that JSONPath can match multiple properties in different object at a nesting level, so it returns an array. – user120242 Jul 04 '20 at 04:50

1 Answers1

1

.query always returns an array of all matches

Find elements in obj matching pathExpression. Returns an array of elements that satisfy the provided JSONPath expression, or an empty array if none were matched. Returns only first count elements if specified.

You are getting from that jsonpath query rolesList = [ [{... rank: ...}, {}, {} ...] ], so sort is acting on a single element array.

You can use .value instead to get the first match found.

$..roles is unnecessary, unless you need to get arbitrary nested level properties, which is not the case here. It's accessible at the first level.

I've used CORS anywhere so this can be run in the browser (codesandbox here):

var request = require('request');
var jp = require('jsonpath');
var options = {
  'method': 'GET',
  'url': 'https://cors-anywhere.herokuapp.com/https://groups.roblox.com/v1/groups/2642914/roles',
  'headers': {
  }
};
request(options, function (error, response) {
  if (error) console.error(error);
  var obj = JSON.parse(response.body);
  var rolesList = jp.value(obj, '$.roles');
  rolesList.sort(function(a, b) {
    return a.rank - b.rank;
  });
  
  console.log(rolesList)
});
user120242
  • 14,918
  • 3
  • 38
  • 52