Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I sort a JSON object by a nested value?

I have an ajax call that returns a JSON object that is pretty complex and I'm having a hard time sorting it.

My call:

$.post('/reports-ajax',arguments, function(data) {}

The response:

{
"10001":{
    "unitname":"Fort Worth",
    "discounts":{"12-02-2012":"34.810000","12-03-2012":"20.810000","12-04-2012":"27.040000"},
    "gross":{"12-02-2012":"56.730000","12-03-2012":"19.350000","12-04-2012":"66.390000"},
    "net":{"12-02-2012":"61.920000","12-03-2012":"98.540000","12-04-2012":"39.350000"},
    "discounts_total":82.66,
    "gross_total":82.47,
    "net_total":99.81,
    "number":10001
    },
"10002":{
    "unitname":"Dallast",
    "discounts":{"12-02-2012":"12.600000","12-03-2012":"25.780000","12-04-2012":"47.780000","12-05-2012":"45.210000"},
    "gross":{"12-02-2012":"29.370000","12-03-2012":"91.110000","12-04-2012":"60.890000","12-05-2012":"51.870000"},
    "net":{"12-02-2012":"16.770000","12-03-2012":"65.330000","12-04-2012":"13.110000","12-05-2012":"06.660000"},
    "discounts_total":131.37,
    "gross_total":33.24,
    "net_total":101.87,
    "number":10002
    },
"32402":{
    "unitname":"Austin",
    "discounts":{"12-05-2012":"52.890000","12-02-2012":"22.430000","12-03-2012":"58.420000","12-04-2012":"53.130000"},
    "gross":{"12-05-2012":"25.020000","12-02-2012":"2836.010000","12-03-2012":"54.740000","12-04-2012":"45.330000"},
    "net":{"12-04-2012":"92.200000","12-05-2012":"72.130000","12-02-2012":"13.580000","12-03-2012":"96.320000"},
    "discounts_total":186.87,
    "gross_total":161.1,
    "net_total":174.23,
    "number":32402
    }
}

I go over the function with a standard each call and do some awesome stuff with highcharts but now I'm trying to sort the responses by the net_total call and I can't figure it out.

I tried .sort() and it errors out that its not a function. I've been reading for a while but guess I'm not finding the right results. This looked promising: Sorting an array of JavaScript objects but it failed with the .sort is not a function. It seems most .sort are on [] arrays not full objects..

Any help would be greatly appreciated.

like image 627
Dennis Smolek Avatar asked Dec 07 '12 07:12

Dennis Smolek


People also ask

How do I sort items in JSON?

JSON return type is an array of objects. Hence sort method cannot be used directly to sort the array. However, we can use a comparer function as the argument of the 'sort' method to get the sorting implemented.

Can you nest objects in JSON?

Objects can be nested inside other objects. Each nested object must have a unique access path. The same field name can occur in nested objects in the same document.

Does JSON support nested values?

Attributes and event data can contain nested (JSON) values—arrays, objects, and arrays of objects.

How do you sort a JSON object based on value in python?

Using json. dumps() function is one way to sort the JSON object. It is used to convert the array of JSON objects into a sorted JSON object. The value of the sort_keys argument of the dumps() function will require to set True to generate the sorted JSON objects from the array of JSON objects.


2 Answers

Sorting objects doesn't make sense since object keys have no positional value. For example, this:

{ a:1, b:2 }

and this:

{ b:2, a:1 }

are exactly the same object. They're not just similar, they're the same.

Nothing in javascript per se gives object keys any positional value. Some people perhaps are mistaken in the belief that:

for (var key in obj) {

iterates through the object keys in a specific sequence. But this is wrong. You should always assume that the for .. in loop processes object keys in random order, always, all the time.

Obviously, if you're going to write a web browser, you're not going to implement a random number generator to parse a for .. in loop. Therefore most web browsers have an accidental stability to how the for .. in loop processes object keys.

Developers who learn javascript by playing around with the browser may figure out that their browser iterates through objects in alphabetical order for example, or the order the keys were added to the object. But this is totally accidental and cannot be relied upon. The browser vendor may change this behavior in the future without violating any backwards compatability (except with buggy scripts written by people who believe objects have a sort order). Not to mention that different browsers have different implementations of javascript and therefore not necessarily have the same internal key ordering of objects.

All the above is besides the point. "Key sort order" does not make any sense in javascript and any behavior observed is merely implementation detail. In short, javascript object does not have key order, just assume it's random.


Solution

Now, what you're really trying to do is not sort the object (you can't, it doesn't make sense). What you're really trying to do is process the object attributes in a specific order. The solution is to simply create an array (which has sorting order) of object keys and then process the object using that array:

// First create the array of keys/net_total so that we can sort it:
var sort_array = [];
for (var key in Response) {
    sort_array.push({key:key,net_total:Response[key].net_total});
}

// Now sort it:
sort_array.sort(function(x,y){return x.net_total - y.net_total});

// Now process that object with it:
for (var i=0;i<sort_array.length;i++) {
    var item = Response[sort_array[i].key];

    // now do stuff with each item
}
like image 143
slebetman Avatar answered Sep 22 '22 10:09

slebetman


What you have there isn't an array and has no order, so you'll have to transform it into an array so you can give it order.

Vaguely:

var array = [];
$.each(data, function(key, value) {
    array.push(value);
});
array.sort(function(a, b) {
    return a.net_total - b.net_total;
});

Live Example | Source

As GolezTroi points out in the comments, normally the above would lose the key that each entry is stored under in data and so you'd add it back in the first $.each loop above, but in this case the entries already have the key on them (as number), so there's no need.

Or you can replace the first $.each with $.map:

var array = $.map(data, function(entry) {
    return entry;
});
// ...and then sort etc.

...whichever you prefer.

like image 22
T.J. Crowder Avatar answered Sep 22 '22 10:09

T.J. Crowder