JSON stringifiziert einen Satz


97

Wie würde ein JSON.stringify () ein Set ?

Dinge, die in Chromium 43 nicht funktionierten:

var s = new Set(['foo', 'bar']);

JSON.stringify(s); // -> "{}"
JSON.stringify(s.values()); // -> "{}"
JSON.stringify(s.keys()); // -> "{}"

Ich würde erwarten, etwas Ähnliches wie ein serialisiertes Array zu bekommen.

JSON.stringify(["foo", "bar"]); // -> "["foo","bar"]"

Antworten:


104

JSON.stringify funktioniert nicht direkt mit Sets, da die im Set gespeicherten Daten nicht als Eigenschaften gespeichert werden.

Sie können das Set jedoch in ein Array konvertieren. Dann können Sie es richtig stringifizieren.

Eine der folgenden Möglichkeiten reicht aus:

JSON.stringify([...s]);
JSON.stringify([...s.keys()]);
JSON.stringify([...s.values()]);
JSON.stringify(Array.from(s));
JSON.stringify(Array.from(s.keys()));
JSON.stringify(Array.from(s.values()));

2
Ich wollte vorschlagen Array.from(). Das sieht aber idiomisch besser aus.
TaoPR

3
Nur um eine Referenz hinzuzufügen MDN hat einige Beispiele für diese und andere verwandte Techniken
Amit

5
Ein Listenverständnis könnte auch funktionieren:JSON.stringify([_ for (_ of s)])
Whymarrh

1
Alle großartigen Möglichkeiten, leider funktionieren sie in Chromium 43 nicht sofort, da Spread und Array.from noch nicht implementiert sind. Sieht aus wie Babel zur Rettung.
MitMaro

2
Ein aktueller Vorschlag zur Verbesserung der Standardeinstellung von Set.prototype.toJSON: github.com/DavidBruant/Map-Set.prototype.toJSON
Oncle Tom

34

Verwenden Sie diesen JSON.stringifyErsatz:

(Da toJSONes sich um ein altes Artefakt handelt und ein besserer Ansatz darin besteht, ein benutzerdefiniertes Artefakt zu verwendenreplacer , siehe https://github.com/DavidBruant/Map-Set.prototype.toJSON/issues/16 )

function Set_toJSON(key, value) {
  if (typeof value === 'object' && value instanceof Set) {
    return [...value];
  }
  return value;
}

Dann:

const fooBar = { foo: new Set([1, 2, 3]), bar: new Set([4, 5, 6]) };
JSON.stringify(fooBar, Set_toJSON)

Ergebnis:

"{"foo":[1,2,3],"bar":[4,5,6]}"

5
Es gibt eine verkürzte Version in ES6JSON.stringify(fooBar, (key, value) => value instanceof Set ? [...value] : value)
OzzyCzech

Der entsprechende Reviver bleibt als Übung für den Leser? ;-)
Robert Siemer

7

Während all die oben genannten Arbeiten, schlage ich vor, dass Sie eine Unterklasse festlegen und eine toJSONMethode hinzufügen , um sicherzustellen, dass die Zeichenfolge korrekt ist. Vor allem, wenn Sie häufig fädeln werden. Ich verwende Sets in meinen Redux-Filialen und musste sicherstellen, dass dies nie ein Problem war.

Dies ist eine grundlegende Implementierung. Die Benennung dient nur zur Veranschaulichung des Punktes, bei dem Sie Ihren eigenen Stil auswählen.

class JSONSet extends Set {
    toJSON () {
        return [...this]
    }
}

const set = new JSONSet([1, 2, 3])
console.log(JSON.stringify(set))

4
Ich würde diesen Ansatz nicht empfehlen, da er toJSONals Legacy-Funktion angesehen wird. Ein Vorschlag hinzufügen , toJSONum beide setund mapwurde abgelehnt: github.com/DavidBruant/Map-Set.prototype.toJSON/issues/16
MitMaro

Überschreiben constructorist nicht erforderlich.
Justin Johnson
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.