JSON)JSON-API.stringfy(): Angabe, welche Eigenschaften von Objekten stringifiziert werden sollen.stringify() und .parse(): WertbesucherJSON („JavaScript Object Notation“) ist ein Speicherformat, das Text zur Kodierung von Daten verwendet. Seine Syntax ist eine Untermenge von JavaScript-Ausdrücken. Betrachten Sie als Beispiel den folgenden Text, der in einer Datei jane.json gespeichert ist.
{
"first": "Jane",
"last": "Porter",
"married": true,
"born": 1890,
"friends": [ "Tarzan", "Cheeta" ]
}JavaScript hat das globale Namensraumobjekt JSON, das Methoden zum Erstellen und Parsen von JSON bereitstellt.
Eine Spezifikation für JSON wurde 2001 von Douglas Crockford unter json.org veröffentlicht. Er erklärt:
Ich habe JSON entdeckt. Ich behaupte nicht, JSON erfunden zu haben, denn es existierte bereits in der Natur. Was ich tat, war, es zu finden, ihm einen Namen zu geben und zu beschreiben, wie es nützlich war. Ich behaupte nicht, die erste Person zu sein, die es entdeckt hat; ich weiß, dass es andere Leute gab, die es mindestens ein Jahr vor mir entdeckt haben. Das früheste Vorkommen, das ich gefunden habe, war bei jemandem bei Netscape, der JavaScript-Array-Literale zur Datenkommunikation bereits 1996 verwendete, was mindestens fünf Jahre war, bevor ich auf die Idee stieß.
Später wurde JSON als ECMA-404 standardisiert.
Zitiert aus dem ECMA-404-Standard:
Da sie so einfach ist, wird nicht erwartet, dass sich die JSON-Grammatik jemals ändern wird. Dies verleiht JSON als grundlegender Notation eine enorme Stabilität.
Daher wird JSON niemals Verbesserungen wie optionale abschließende Kommas, Kommentare oder unzitierte Schlüssel erhalten – unabhängig davon, ob sie als wünschenswert erachtet werden oder nicht. Dies lässt jedoch Raum für die Erstellung von Obermengen von JSON, die zu einfachem JSON kompiliert werden.
JSON besteht aus den folgenden Teilen von JavaScript:
null (aber nicht undefined)NaN, +Infinity, -Infinity)Infolgedessen können Sie zyklische Strukturen in JSON nicht (direkt) darstellen.
JSON-APIDas globale Namensraumobjekt JSON enthält Methoden für die Arbeit mit JSON-Daten.
JSON.stringify(data, replacer?, space?).stringify() konvertiert JavaScript-data in einen JSON-String. In diesem Abschnitt ignorieren wir den Parameter replacer; er wird in §45.4 „Anpassen von Stringifying und Parsen“ erklärt.
Wenn Sie nur das erste Argument angeben, gibt .stringify() eine einzelne Textzeile zurück.
assert.equal(
JSON.stringify({foo: ['a', 'b']}),
'{"foo":["a","b"]}' );Wenn Sie eine nicht-negative Ganzzahl für space angeben, gibt .stringify() eine oder mehrere Zeilen zurück und rückt mit space Leerzeichen pro Verschachtelungsebene ein.
assert.equal(
JSON.stringify({foo: ['a', 'b']}, null, 2),
`{
"foo": [
"a",
"b"
]
}`);Primitive Werte
Unterstützte primitive Werte werden wie erwartet stringifiziert.
> JSON.stringify('abc')
'"abc"'
> JSON.stringify(123)
'123'
> JSON.stringify(null)
'null'Nicht unterstützte Zahlen: 'null'
> JSON.stringify(NaN)
'null'
> JSON.stringify(Infinity)
'null'Bigints: TypeError
> JSON.stringify(123n)
TypeError: Do not know how to serialize a BigIntAndere nicht unterstützte primitive Werte werden nicht stringifiziert; sie ergeben das Ergebnis undefined.
> JSON.stringify(undefined)
undefined
> JSON.stringify(Symbol())
undefinedObjekte
Wenn ein Objekt eine Methode .toJSON() hat, wird das Ergebnis dieser Methode stringifiziert.
> JSON.stringify({toJSON() {return true}})
'true'Daten haben eine Methode .toJSON(), die eine Zeichenkette zurückgibt.
> JSON.stringify(new Date(2999, 11, 31))
'"2999-12-30T23:00:00.000Z"'Eingewickelte primitive Werte werden entpackt und stringifiziert.
> JSON.stringify(new Boolean(true))
'true'
> JSON.stringify(new Number(123))
'123'Arrays werden als Array-Literale stringifiziert. Nicht unterstützte Array-Elemente werden so stringifiziert, als wären sie null.
> JSON.stringify([undefined, 123, Symbol()])
'[null,123,null]'Alle anderen Objekte – außer Funktionen – werden als Objektliterale stringifiziert. Eigenschaften mit nicht unterstützten Werten werden weggelassen.
> JSON.stringify({a: Symbol(), b: true})
'{"b":true}'Funktionen werden nicht stringifiziert.
> JSON.stringify(() => {})
undefinedJSON.parse(text, reviver?).parse() konvertiert einen JSON-text in einen JavaScript-Wert. In diesem Abschnitt ignorieren wir den Parameter reviver; er wird in §45.4 „Anpassen von Stringifying und Parsen“ erklärt.
Dies ist ein Beispiel für die Verwendung von .parse().
> JSON.parse('{"foo":["a","b"]}')
{ foo: [ 'a', 'b' ] }Die folgende Klasse implementiert Konvertierungen von (Zeile A) und nach (Zeile B) JSON.
class Point {
static fromJson(jsonObj) { // (A)
return new Point(jsonObj.x, jsonObj.y);
}
constructor(x, y) {
this.x = x;
this.y = y;
}
toJSON() { // (B)
return {x: this.x, y: this.y};
}
}Konvertierung von JSON in einen Punkt: Wir verwenden die statische Methode Point.fromJson(), um JSON zu parsen und eine Instanz von Point zu erstellen.
assert.deepEqual(
Point.fromJson(JSON.parse('{"x":3,"y":5}')),
new Point(3, 5) );Konvertierung eines Punktes in JSON: JSON.stringify() ruft intern die zuvor erwähnte Methode .toJSON() auf.
assert.equal(
JSON.stringify(new Point(3, 5)),
'{"x":3,"y":5}' ); Übung: Konvertierung eines Objekts von und nach JSON
exercises/json/to_from_json_test.mjs
Stringifying und Parsen können wie folgt angepasst werden:
JSON.stringify(data, replacer?, space?)
Der optionale Parameter replacer enthält entweder
data als Objektliteral stringifiziert wird, werden nur die genannten Eigenschaften berücksichtigt. Alle anderen Eigenschaften werden ignoriert.JSON.parse(text, reviver?)
Der optionale Parameter reviver enthält einen Wertbesucher, der die geparsten JSON-Daten transformieren kann, bevor sie zurückgegeben werden.
.stringfy(): Angabe, welche Eigenschaften von Objekten stringifiziert werden sollenWenn der zweite Parameter von .stringify() ein Array ist, dann werden nur die Objekteigenschaften, deren Namen dort genannt sind, in das Ergebnis aufgenommen.
const obj = {
a: 1,
b: {
c: 2,
d: 3,
}
};
assert.equal(
JSON.stringify(obj, ['b', 'c']),
'{"b":{"c":2}}');.stringify() und .parse(): WertbesucherWas ich als Wertbesucher bezeichne, ist eine Funktion, die JavaScript-Daten transformiert.
JSON.stringify() lässt den Wertbesucher in seinem Parameter replacer JavaScript-Daten transformieren, bevor sie stringifiziert werden.JSON.parse() lässt den Wertbesucher in seinem Parameter reviver geparste JavaScript-Daten transformieren, bevor sie zurückgegeben werden.In diesem Abschnitt werden JavaScript-Daten als Baum von Werten betrachtet. Wenn die Daten atomar sind, ist es ein Baum, der nur einen Wurzelknoten hat. Alle Werte im Baum werden nacheinander an den Wertbesucher übergeben. Je nachdem, was der Besucher zurückgibt, wird der aktuelle Wert weggelassen, geändert oder beibehalten.
Ein Wertbesucher hat die folgende Typsignatur:
type ValueVisitor = (key: string, value: any) => any;Die Parameter sind:
value: Der aktuelle Wert.this: Elternteil des aktuellen Werts. Der Elternteil des Wurzelwerts r ist {'': r}.this ist ein impliziter Parameter und nur verfügbar, wenn der Wertbesucher eine gewöhnliche Funktion ist.key: Schlüssel oder Index des aktuellen Werts innerhalb seines Elternteils. Der Schlüssel des Wurzelwerts ist ''.Der Wertbesucher kann zurückgeben:
value: bedeutet, es wird keine Änderung vorgenommen.x: führt dazu, dass value durch x im Ausgabebaum ersetzt wird.undefined: führt dazu, dass value im Ausgabebaum weggelassen wird.Der folgende Code zeigt, in welcher Reihenfolge ein Wertbesucher Werte sieht.
const log = [];
function valueVisitor(key, value) {
log.push({this: this, key, value});
return value; // no change
}
const root = {
a: 1,
b: {
c: 2,
d: 3,
}
};
JSON.stringify(root, valueVisitor);
assert.deepEqual(log, [
{ this: { '': root }, key: '', value: root },
{ this: root , key: 'a', value: 1 },
{ this: root , key: 'b', value: root.b },
{ this: root.b , key: 'c', value: 2 },
{ this: root.b , key: 'd', value: 3 },
]);Wie wir sehen können, besucht der Replacer von JSON.stringify() Werte von oben nach unten (Wurzel zuerst, Blätter zuletzt). Das Motiv für diese Richtung ist, dass wir JavaScript-Werte in JSON-Werte konvertieren. Und ein einzelnes JavaScript-Objekt kann in einen Baum von JSON-kompatiblen Werten erweitert werden.
Im Gegensatz dazu besucht der Reviver von JSON.parse() Werte von unten nach oben (Blätter zuerst, Wurzel zuletzt). Das Motiv für diese Richtung ist, dass wir JSON-Werte zu JavaScript-Werten zusammensetzen. Daher müssen wir die Teile konvertieren, bevor wir das Ganze konvertieren können.
JSON.stringify() hat keine spezielle Unterstützung für reguläre Ausdrucksobjekte – es stringifiziert sie, als wären sie einfache Objekte.
const obj = {
name: 'abc',
regex: /abc/ui,
};
assert.equal(
JSON.stringify(obj),
'{"name":"abc","regex":{}}');Wir können das über einen Replacer beheben:
function replacer(key, value) {
if (value instanceof RegExp) {
return {
__type__: 'RegExp',
source: value.source,
flags: value.flags,
};
} else {
return value; // no change
}
}
assert.equal(
JSON.stringify(obj, replacer, 2),
`{
"name": "abc",
"regex": {
"__type__": "RegExp",
"source": "abc",
"flags": "iu"
}
}`);Um das Ergebnis aus dem vorherigen Abschnitt mit JSON.parse() zu parsen, benötigen wir einen Reviver.
function reviver(key, value) {
// Very simple check
if (value && value.__type__ === 'RegExp') {
return new RegExp(value.source, value.flags);
} else {
return value;
}
}
const str = `{
"name": "abc",
"regex": {
"__type__": "RegExp",
"source": "abc",
"flags": "iu"
}
}`;
assert.deepEqual(
JSON.parse(str, reviver),
{
name: 'abc',
regex: /abc/ui,
});Douglas Crockford erklärt dies in einem Google+ Post vom 1. Mai 2012.
Ich habe Kommentare aus JSON entfernt, weil ich sah, dass Leute sie für Parsing-Direktiven verwendeten, eine Praxis, die die Interoperabilität zerstört hätte. Ich weiß, dass das Fehlen von Kommentaren einige Leute traurig macht, aber das sollte es nicht.
Angenommen, Sie verwenden JSON, um Konfigurationsdateien zu speichern, die Sie kommentieren möchten. Fügen Sie einfach alle gewünschten Kommentare ein. Leiten Sie sie dann durch JSMin [einen Minifier für JavaScript], bevor Sie sie an Ihren JSON-Parser übergeben.