La risposta accettata non funziona per me per gli oggetti nidificati per qualche motivo. Questo mi ha portato a programmare il mio. Dato che è la fine del 2019 quando scrivo questo, ci sono alcune altre opzioni disponibili nella lingua.
Aggiornamento: credo che la risposta di David Furlong sia un approccio preferibile al mio tentativo precedente, e l'ho respinto. Il mio si basa sul supporto per Object.entries (...), quindi nessun supporto per Internet Explorer.
function normalize(sortingFunction) {
return function(key, value) {
if (typeof value === 'object' && !Array.isArray(value)) {
return Object
.entries(value)
.sort(sortingFunction || undefined)
.reduce((acc, entry) => {
acc[entry[0]] = entry[1];
return acc;
}, {});
}
return value;
}
}
JSON.stringify(obj, normalize(), 2);
-
MANTENENDO QUESTA VERSIONE VECCHIA PER RIFERIMENTO STORICO
Ho scoperto che funzionerà un array semplice e piatto di tutte le chiavi dell'oggetto. In quasi tutti i browser (non Edge o Internet Explorer, prevedibilmente) e Node 12+ c'è una soluzione abbastanza breve ora che Array.prototype.flatMap (...) è disponibile. (Anche l'equivalente lodash funzionerebbe.) Ho testato solo in Safari, Chrome e Firefox, ma non vedo motivo per cui non funzionerebbe da nessun'altra parte che supporti flatMap e JSON.stringify standard (...) .
function flattenEntries([key, value]) {
return (typeof value !== 'object')
? [ [ key, value ] ]
: [ [ key, value ], ...Object.entries(value).flatMap(flattenEntries) ];
}
function sortedStringify(obj, sorter, indent = 2) {
const allEntries = Object.entries(obj).flatMap(flattenEntries);
const sorted = allEntries.sort(sorter || undefined).map(entry => entry[0]);
return JSON.stringify(obj, sorted, indent);
}
Con questo, puoi stringere senza dipendenze di terze parti e persino passare il tuo algoritmo di ordinamento che ordina le coppie di voci chiave-valore, in modo da poter ordinare per chiave, payload o una combinazione dei due. Funziona per oggetti annidati, array e qualsiasi combinazione di vecchi tipi di dati.
const obj = {
"c": {
"z": 4,
"x": 3,
"y": [
2048,
1999,
{
"x": false,
"g": "help",
"f": 5
}
]
},
"a": 2,
"b": 1
};
console.log(sortedStringify(obj, null, 2));
Stampe:
{
"a": 2,
"b": 1,
"c": {
"x": 3,
"y": [
2048,
1999,
{
"f": 5,
"g": "help",
"x": false
}
],
"z": 4
}
}
Se è necessario disporre della compatibilità con i motori JavaScript precedenti , è possibile utilizzare queste versioni leggermente più dettagliate che emulano il comportamento di flatMap. Il client deve supportare almeno ES5, quindi non Internet Explorer 8 o inferiore.
Questi restituiranno lo stesso risultato come sopra.
function flattenEntries([key, value]) {
if (typeof value !== 'object') {
return [ [ key, value ] ];
}
const nestedEntries = Object
.entries(value)
.map(flattenEntries)
.reduce((acc, arr) => acc.concat(arr), []);
nestedEntries.unshift([ key, value ]);
return nestedEntries;
}
function sortedStringify(obj, sorter, indent = 2) {
const sortedKeys = Object
.entries(obj)
.map(flattenEntries)
.reduce((acc, arr) => acc.concat(arr), [])
.sort(sorter || undefined)
.map(entry => entry[0]);
return JSON.stringify(obj, sortedKeys, indent);
}