Meine Anwendung verfügt über eine große Anzahl von Objekten, die ich anordne und auf der Festplatte speichere. Wenn die Objekte im Array bearbeitet und manchmal ersetzt werden, werden die Eigenschaften der Objekte leider in verschiedenen Reihenfolgen aufgelistet (ihre Erstellungsreihenfolge?). Wenn ich JSON.stringify () für das Array ausführe und es speichere, zeigt ein Diff die Eigenschaften an, die in verschiedenen Reihenfolgen aufgelistet werden. Dies ist ärgerlich, wenn versucht wird, die Daten mit Diff- und Zusammenführungswerkzeugen weiter zusammenzuführen.
Idealerweise möchte ich die Eigenschaften der Objekte in alphabetischer Reihenfolge sortieren, bevor ich die Zeichenfolge ausführe, oder als Teil der Zeichenfolgeoperation. Es gibt Code zum Bearbeiten der Array-Objekte an vielen Stellen, und es wäre schwierig, diese zu ändern, um Eigenschaften immer in einer expliziten Reihenfolge zu erstellen.
Vorschläge wären herzlich willkommen!
Ein komprimiertes Beispiel:
obj = {}; obj.name="X"; obj.os="linux";
JSON.stringify(obj);
obj = {}; obj.os="linux"; obj.name="X";
JSON.stringify(obj);
Die Ausgabe dieser beiden Stringify-Aufrufe ist unterschiedlich und wird in einem Unterschied meiner Daten angezeigt, aber meine Anwendung kümmert sich nicht um die Reihenfolge der Eigenschaften. Die Objekte sind auf viele Arten und Orte konstruiert.
quelle
Antworten:
Der einfachere, modernere und derzeit vom Browser unterstützte Ansatz lautet einfach:
Diese Methode entfernt jedoch alle verschachtelten Objekte, auf die nicht verwiesen wird, und gilt nicht für Objekte in Arrays. Sie sollten das Sortierobjekt auch reduzieren, wenn Sie so etwas wie diese Ausgabe möchten:
Das können Sie damit machen:
Um dies programmgesteuert mit etwas zu tun, das Sie selbst optimieren können, müssen Sie die Objekteigenschaftsnamen in ein Array verschieben, dann das Array alphabetisch sortieren und durch dieses Array (das in der richtigen Reihenfolge angeordnet ist) iterieren und jeden Wert aus dem Objekt in auswählen diese Reihenfolge. "hasOwnProperty" ist ebenfalls aktiviert, sodass Sie definitiv nur die eigenen Eigenschaften des Objekts haben. Hier ist ein Beispiel:
Auch dies sollte sicherstellen, dass Sie in alphabetischer Reihenfolge durchlaufen.
Mit dieser Bibliothek können Sie auf einfachste Weise rekursiv nach JSON sortieren, das Sie an sie übergeben: https://www.npmjs.com/package/json-stable-stringify
Ausgabe
quelle
obj[i]
in der for-Schleife nicht referenzieren , dai
es sich um eine Ganzzahl handelt und die Eigenschaftsnamen nicht unbedingt (daher diese Frage). Es sollte seinobj[arr[i]]
.iterateObjectAlphabetically
zu einer wiederverwendbaren Funktion. Ohne den Rückruf müsste sich der 'Payload Code' in der Funktion selbst befinden. Ich denke, es ist eine sehr elegante Lösung, die in vielen Bibliotheken und im JS-Kern selbst verwendet wird. ZB Array.forEach .Ich denke, wenn Sie die Kontrolle über die JSON-Generation haben (und es klingt so, als ob Sie es sind), könnte dies für Ihre Zwecke eine gute Lösung sein: json-Stable-Stringify
Von der Projektwebsite:
Wenn der erzeugte JSON deterministisch ist, sollten Sie ihn leicht unterscheiden / zusammenführen können.
quelle
Sie können ein sortiertes Array der Eigenschaftsnamen als zweites Argument übergeben
JSON.stringify()
:quelle
JSON.stringify()
aufgerufenreplacer
und kann ein Array sein. Es wird verwendet, um ein zu erstellen,PropertyList
das dann verwendet wirdSerializeJSONObject()
, um die Eigenschaften in dieser Reihenfolge anzuhängen. Dies ist seit ECMAScript 5 dokumentiert.> JSON.stringify({a: {c: 1, b: 2}}, ['a']) '{"a":{}}'
Gegenbeispiel : Eine (hackige) Möglichkeit, die Liste aller relevanten Schlüssel zu erstellen, besteht darin, das Objekt mit JSON.stringify zu durchlaufen:function orderedStringify(obj) { const allKeys = []; JSON.stringify(obj, (k, v) => { allKeys.push(k); return v; }); return JSON.stringify(obj, allKeys.sort()); }
Beispiel:> orderedStringify({a: {c: 1, b: 2}}) '{"a":{"b":2,"c":1}}'
Ich verstehe nicht, warum die Komplexität der aktuell besten Antworten erforderlich ist, um alle Schlüssel rekursiv zu erhalten. Wenn keine perfekte Leistung erforderlich ist, können wir meines Erachtens nur
JSON.stringify()
zweimal anrufen , das erste Mal, um alle Schlüssel zu erhalten, und das zweite Mal, um die Arbeit wirklich zu erledigen. Auf diese Weise wird die gesamte Rekursionskomplexität von behandeltstringify
, und wir wissen, dass sie sich auskennt und wie mit jedem Objekttyp umgegangen wird:quelle
Object.keys()
nicht rekursiv ist. Wenn Sie also ein Objekt wie haben{a: "A", b: {c: "C"} }
und Object.keys darauf aufrufen, erhalten Sie nur Schlüssela
undb
, aber nichtc
.JSON.stringify
weiß alles über die Rekursion für jeden Objekttyp, der vom JSON-Serialisierungsprozess verarbeitet wird, sei es ein objektähnlicher oder ein Array (und es implementiert bereits die Logik, um beide zu erkennen), daher sollte alles für uns korrekt behandelt werden.Update 2018-7-24:
Diese Version sortiert verschachtelte Objekte und unterstützt auch Arrays:
Testfall:
Veraltete Antwort:
Eine prägnante Version in ES2016. Gutschrift an @codename von https://stackoverflow.com/a/29622653/94148
quelle
function orderedJsonStringify(o) { return JSON.stringify(Object.keys(o).sort().reduce((r, k) => (r[k] = o[k], r), {})); }
sortObjByKey()
Zirkelverweisen sucht. Seien Sie also vorsichtig, es kann abhängig von den Eingabedaten in einer Endlosschleife hängen bleiben. Beispiel:var objA = {}; var objB = {objA: objA}; objA.objB = objB;
->sortObjByKey(objA);
->VM59:6 Uncaught RangeError: Maximum call stack size exceeded
https://gist.github.com/davidfurlong/463a83a33b70a3b6618e97ec9679e490
quelle
Dies ist die gleiche Antwort wie Satpal Singh
quelle
Sie können eine benutzerdefinierte hinzufügen
toJSON
Ihrem Objekt Funktion der Sie die Ausgabe anpassen können. Innerhalb der Funktion sollte das Hinzufügen aktueller Eigenschaften zu einem neuen Objekt in einer bestimmten Reihenfolge diese Reihenfolge beim Stringifizieren beibehalten.Siehe hier:
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/JSON/stringify
Es gibt keine integrierte Methode zur Steuerung der Reihenfolge, da auf JSON-Daten über Schlüssel zugegriffen werden soll.
Hier ist eine jsfiddle mit einem kleinen Beispiel:
http://jsfiddle.net/Eq2Yw/
Versuchen Sie, die
toJSON
Funktion auskommentieren - die Reihenfolge der Eigenschaften ist umgekehrt. Bitte beachten Sie, dass dies möglicherweise browserspezifisch ist, dh die Bestellung wird in der Spezifikation nicht offiziell unterstützt. Es funktioniert in der aktuellen Version von Firefox, aber wenn Sie eine 100% robuste Lösung wünschen, müssen Sie möglicherweise Ihre eigene Stringifier-Funktion schreiben.Bearbeiten:
Siehe auch diese SO-Frage zur nicht deterministischen Ausgabe von stringify, insbesondere zu Daffs Details zu Browserunterschieden:
Wie kann deterministisch überprüft werden, ob ein JSON-Objekt nicht geändert wurde?
quelle
Eine rekursive und vereinfachte Antwort:
quelle
reorder
sollte umbenannt werden insortObject
und dies behandelt keine Arraystypeof arr === "object"
Arrays in Objekte umgewandelt werden. Zum Beispielvar obj = {foo: ["bar", "baz"]}
würde in{ "foo": { "0": "bar", "1": "baz"} }
if(obj.constructor.prototype !== Object.prototype)
Sie können Objekte in EcmaScript 2015 nach Eigenschaftsnamen sortieren
quelle
sortObjectPropertiesByName()
oder einfachersortPropertiesByName()
.Ich habe die Antwort von @Jason Parham genommen und einige Verbesserungen vorgenommen
Dies behebt das Problem, dass Arrays in Objekte konvertiert werden, und Sie können auch festlegen, wie Arrays sortiert werden sollen.
Beispiel:
Ausgabe:
quelle
Die akzeptierte Antwort funktioniert bei mir für verschachtelte Objekte aus irgendeinem Grund nicht. Dies führte mich dazu, meine eigenen zu codieren. Da es Ende 2019 ist, als ich dies schreibe, gibt es einige weitere Optionen in der Sprache.
Update: Ich glaube, die Antwort von David Furlong ist ein bevorzugter Ansatz für meinen früheren Versuch, und das habe ich abgehört. Meins ist auf die Unterstützung von Object.entries (...) angewiesen, daher keine Internet Explorer-Unterstützung.
- -
BEHALTEN SIE DIESE ÄLTERE VERSION FÜR HISTORISCHE REFERENZEN
Ich habe festgestellt, dass eine einfache, flache Anordnung aller Schlüssel im Objekt funktioniert. In fast allen Browsern (vorhersehbar nicht Edge oder Internet Explorer) und Node 12+ gibt es jetzt, da Array.prototype.flatMap (...) verfügbar ist, eine ziemlich kurze Lösung . (Das lodash-Äquivalent würde auch funktionieren.) Ich habe nur in Safari, Chrome und Firefox getestet, aber ich sehe keinen Grund, warum es nirgendwo anders funktionieren würde, das flatMap und Standard JSON.stringify (...) unterstützt .
Auf diese Weise können Sie ohne Abhängigkeiten von Drittanbietern eine Zeichenfolge erstellen und sogar Ihren eigenen Sortieralgorithmus übergeben, der die Schlüssel-Wert-Eintragspaare sortiert, sodass Sie nach Schlüssel, Nutzlast oder einer Kombination aus beiden sortieren können. Funktioniert für verschachtelte Objekte, Arrays und jede Mischung aus einfachen alten Datentypen.
Drucke:
Wenn Sie mit älteren JavaScript-Engines kompatibel sein müssen , können Sie diese etwas ausführlicheren Versionen verwenden, die das flatMap-Verhalten emulieren. Der Client muss mindestens ES5 unterstützen, daher kein Internet Explorer 8 oder niedriger.
Diese geben das gleiche Ergebnis wie oben zurück.
quelle
Funktioniert mit lodash, verschachtelten Objekten und jedem Wert des Objektattributs:
Es basiert auf dem Verhalten von Chrome und Node, dass der erste einem Objekt zugewiesene Schlüssel zuerst von ausgegeben wird
JSON.stringify
.quelle
Versuchen:
quelle
Ich habe eine Funktion zum Sortieren von Objekten und mit Rückruf erstellt, die tatsächlich ein neues Objekt erstellt
und nenne es mit Objekt.
welche druckt
{"value":"msio","os":"windows","name":"anu"}
, und zum Sortieren mit Wert.welche druckt
{"os":"windows","value":"msio","name":"anu"}
quelle
Wenn Objekte in der Liste nicht dieselben Eigenschaften haben, generieren Sie vor dem Stringifizieren ein kombiniertes Masterobjekt:
quelle
// Beispiel wie unten. in jeder Ebene für Objekte wie {} in Schlüsselsortierung abgeflacht. für Arrays, Zahlen oder Strings, abgeflacht wie / mit JSON.stringify.
quelle
Erweiterung der Antwort von AJP auf Arrays:
quelle
Überrascht hat niemand die
isEqual
Funktion von lodash erwähnt .Mit dem ursprünglichen Problem - Schlüssel werden uneinheitlich geordnet - ist es eine großartige Lösung - und natürlich hört es einfach auf, wenn es einen Konflikt findet, anstatt das gesamte Objekt blind zu serialisieren.
Um zu vermeiden, dass die gesamte Bibliothek importiert wird, gehen Sie wie folgt vor:
Bonusbeispiel: Sie können dies auch mit RxJS mit diesem benutzerdefinierten Operator verwenden
quelle
Schließlich benötigt es ein Array, das alle Schlüssel im verschachtelten Objekt zwischenspeichert (andernfalls werden die nicht zwischengespeicherten Schlüssel weggelassen). Die älteste Antwort ist einfach falsch, da sich das zweite Argument nicht um die Punktnotation kümmert. So wird die Antwort (mit Set).
quelle
Hier ist ein Klonansatz ... Klonen Sie das Objekt, bevor Sie es in json konvertieren:
If ist sehr neu, scheint aber bei package.json-Dateien gut zu funktionieren.
quelle
Es gibt eine
Array.sort
Methode, die für Sie hilfreich sein kann. Beispielsweise:quelle