Sorting a JavaScript object by property name
Asked Answered
Y

7

75

I've been looking for a while and want a way to sort a Javascript object like this:

{
    method: 'artist.getInfo',
    artist: 'Green Day',
    format: 'json',
    api_key: 'fa3af76b9396d0091c9c41ebe3c63716'
}

and sort is alphabetically by name to get:

{
    api_key: 'fa3af76b9396d0091c9c41ebe3c63716',
    artist: 'Green Day',
    format: 'json',
    method: 'artist.getInfo'
}

I can't find any code that will do this. Can anyone give me some help?

Yamada answered 31/8, 2009 at 22:51 Comment(6)
javascriptkit.com/javatutors/arraysort.shtml - Decent tutorial on sorting complex JS objects. highdots.com/forums/javascript/re-sorting-json-data-270187.html - Another example --- Here is a full reference on the sort function if you want the details developer.mozilla.org/en/Core_JavaScript_1.5_Reference/… -Last edit, I swear!Patinated
The problem I've got is that those articles show how to sort an array of objects. I'm trying to sort an object filled with objects. Will the same examples work for my case, if so could you provide an example? Sorry I'm just really stuck on this one :sYamada
This is an ancient question, but I'm a pedant, so for the billionth time: there is no such thing as a JSON object--at least, not in the way you're referring to it. There are javascript objects and JSON strings.Buchbinder
Upvoted for the artist value. :DJaquelin
There is better answer for ES6 at #5467629Gavriella
@matto1990 Have you tried to use stacksort? :)Frizz
S
101

UPDATE from the comments:

This answer is outdated. In ES6 objects keys are now ordered. See this question for an up-to-date answer

By definition, the order of keys in an object is undefined, so you probably won't be able to do that in a way that is future-proof. Instead, you should think about sorting these keys when the object is actually being displayed to the user. Whatever sort order it uses internally doesn't really matter anyway.

By convention, most browsers will retain the order of keys in an object in the order that they were added. So, you could do this, but don't expect it to always work:

function sortObject(o) {
    var sorted = {},
    key, a = [];

    for (key in o) {
        if (o.hasOwnProperty(key)) {
            a.push(key);
        }
    }

    a.sort();

    for (key = 0; key < a.length; key++) {
        sorted[a[key]] = o[a[key]];
    }
    return sorted;
}
Subadar answered 31/8, 2009 at 23:9 Comment(9)
That seems to work perfectly. I'll have to keep an eye on it breaking in future browsers but it seems to work for now. Thanks for the help :)Yamada
It may in fact always work, and it is being codified into the Ecmascript standard, but it's still not a safe assumption to rely on, because having a defined order is not logically part of an "object". If you want to define order, you should use an array.Anchises
The only reason I need to do it is to sort the values once so I can generate an api signature as defined on this page in section 6: last.fm/api/webauth If I was using it for more than that I'd use an array and them sort that.Yamada
You should most definately use an array for that.Anchises
'if (o.hasOwnProperty(key)) {' It's not necessary, also what about multi level objects, or arrays that contain objects or other way around? It is a good starting point though, mine was similar at first and then I upgraded it a bit... stamat.wordpress.com/2013/07/03/…Rosabella
for case-insensitive sorting of keys replace a.sort(); with a.sort(function (a, b) { return a.toLowerCase().localeCompare(b.toLowerCase());});Tyne
This answer is outdated. In ES6 objects keys are now ordered. See this question for an up-to-date answer!Lx
That one StackSort answer that never does its job...Haughay
This doesn't work for me, order is still as original.Loesceke
A
13

this function takes an object and returns a sorted array of arrays of the form [key,value]

function (o) {
   var a = [],i;
   for(i in o){ 
     if(o.hasOwnProperty(i)){
         a.push([i,o[i]]);
     }
   }
   a.sort(function(a,b){ return a[0]>b[0]?1:-1; })
   return a;
}

The object data structure does not have a well defined order. In mathematical terms, the collection of keys in an object are an Unordered Set, and should be treated as such. If you want to define order, you SHOULD use an array, because an array having an order is an assumption you can rely on. An object having some kind of order is something that is left to the whims of the implementation.

Anchises answered 31/8, 2009 at 23:41 Comment(0)
R
5

Just use sorted stringify() when you need to compare or hash the results.

Renata answered 29/10, 2015 at 11:13 Comment(0)
C
5

Here is a one-liner for you.

Array.prototype.reduce()

let data = {
    method: 'artist.getInfo',
    artist: 'Green Day',
    format: 'json',
    api_key: 'fa3af76b9396d0091c9c41ebe3c63716'
};

let sorted = Object.keys(data).sort().reduce( (acc, currValue) => {
    acc[currValue] = data[currValue];
    return acc;
}, {});

console.log(sorted);

Good luck!!

Chaparro answered 22/10, 2020 at 9:55 Comment(1)
even smaller: Object.keys(data).sort().reduce((o, key) => ({...o, [key]: data[key]}), {})Fascinate
K
3
// if ya need old browser support
Object.keys = Object.keys || function(o) {  
var result = [];  
for(var name in o) {  
    if (o.hasOwnProperty(name))  
      result.push(name);  
}  
    return result;  
};

var o = {c: 3, a: 1, b: 2};
var n = sortem(o);

function sortem(old){
  var newo = {}; Object.keys(old).sort().forEach(function(k) {new[k]=old[k]});
  return newo;
}

// deep
function sortem(old){
  var newo = {}; Object.keys(old).sort().forEach(function(k){ newo[k]=sortem(old[k]) });
  return newo;
}
sortem({b:{b:1,a:2},a:{b:1,a:2}})
Keir answered 4/8, 2013 at 18:1 Comment(3)
Quite nice and slick, but unfortunately Object.keys() is not supported in IE<9 and also not in Quirks mode of any IE>=9. See MSDN's IE Dev Center.Pavkovic
Added poly fill to above answerKeir
If you mean deep sort of the obj, I edited the answer above. The 'new' was a typo.Keir
M
2

ES5 Compatible:

function sortByKey(obj) {
    var keys = Object.keys(obj);
    keys.sort();
    var sorted = {};
    for (var i = 0; i < keys.length; i++) {
        var key = keys[i];
        sorted[key] = obj[key];
    }
    return sorted;
}
Matteo answered 6/8, 2021 at 23:59 Comment(0)
E
0

This should be used with caution as your code shouldn't rely on Object properties order. If it's just a matter of presentation (or just for the fun !), you can sort properties deeply like this :

function sortObject(src) {
  var out;
  if (typeof src === 'object' && Object.keys(src).length > 0) {
    out = {};
    Object.keys(src).sort().forEach(function (key) {
      out[key] = sortObject(src[key]);
    });
    return out;
  }
  return src;
}
Eisenhower answered 3/5, 2018 at 21:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.