sort object properties and JSON.stringify
I don't understand why the complexity of the current best answers is needed, to get all the keys recursively. Unless perfect performance is needed, it seems to me that we can just call JSON.stringify()
twice, the first time to get all the keys, and the second time, to really do the job. That way, all the recursion complexity is handled by stringify
, and we know that it knows its stuff, and how to handle each object type:
function JSONstringifyOrder(obj, space)
{
const allKeys = new Set();
JSON.stringify(obj, (key, value) => (allKeys.add(key), value));
return JSON.stringify(obj, Array.from(allKeys).sort(), space);
}
Or if you want to support older browsers:
function JSONstringifyOrder(obj, space)
{
var allKeys = [];
var seen = {};
JSON.stringify(obj, function (key, value) {
if (!(key in seen)) {
allKeys.push(key);
seen[key] = null;
}
return value;
});
allKeys.sort();
return JSON.stringify(obj, allKeys, space);
}
The simpler, modern and currently browser supported approach is simply this:
JSON.stringify(sortMyObj, Object.keys(sortMyObj).sort());
However, this method does remove any nested objects that aren't referenced and does not apply to objects within arrays. You will want to flatten the sorting object as well if you want something like this output:
{"a":{"h":4,"z":3},"b":2,"c":1}
You can do that with this:
var flattenObject = function(ob) {
var toReturn = {};
for (var i in ob) {
if (!ob.hasOwnProperty(i)) continue;
if ((typeof ob[i]) == 'object') {
var flatObject = flattenObject(ob[i]);
for (var x in flatObject) {
if (!flatObject.hasOwnProperty(x)) continue;
toReturn[i + '.' + x] = flatObject[x];
}
} else {
toReturn[i] = ob[i];
}
}
return toReturn;
};
var myFlattenedObj = flattenObject(sortMyObj);
JSON.stringify(myFlattenedObj, Object.keys(myFlattenedObj).sort());
To do it programmatically with something you can tweak yourself, you need to push the object property names into an array, then sort the array alphabetically and iterate through that array (which will be in the right order) and select each value from the object in that order. "hasOwnProperty" is checked also so you definitely have only the object's own properties. Here's an example:
var obj = {"a":1,"b":2,"c":3};
function iterateObjectAlphabetically(obj, callback) {
var arr = [],
i;
for (i in obj) {
if (obj.hasOwnProperty(i)) {
arr.push(i);
}
}
arr.sort();
for (i = 0; i < arr.length; i++) {
var key = obj[arr[i]];
//console.log( obj[arr[i]] ); //here is the sorted value
//do what you want with the object property
if (callback) {
// callback returns arguments for value, key and original object
callback(obj[arr[i]], arr[i], obj);
}
}
}
iterateObjectAlphabetically(obj, function(val, key, obj) {
//do something here
});
Again, this should guarantee that you iterate through in alphabetical order.
Finally, taking it further for the simplest way, this library will recursively allow you to sort any JSON you pass into it: https://www.npmjs.com/package/json-stable-stringify
var stringify = require('json-stable-stringify');
var obj = { c: 8, b: [{z:6,y:5,x:4},7], a: 3 };
console.log(stringify(obj));
Output
{"a":3,"b":[{"x":4,"y":5,"z":6},7],"c":8}