Die `JSON`-Klasse in JavaScript
Dieser Artikel erklärt die JSON-Klasse in JavaScript.
Wir erklären die JSON-Klasse in JavaScript anhand praktischer Beispiele.
YouTube Video
Die JSON-Klasse in JavaScript
Das JSON-Objekt verfügt hauptsächlich über zwei Methoden. JSON.stringify() wandelt ein Objekt in einen JSON-String um, und JSON.parse() erstellt ein Objekt aus einem JSON-String. JSON ist ein Datenaustauschformat, das nur einige JavaScript-Werte darstellen kann. Funktionen, undefined, Symbol und zirkuläre Verweise können nicht direkt in JSON konvertiert werden.
JSON.stringify()
Zunächst ein einfaches Beispiel, wie ein Objekt in einen JSON-String konvertiert wird.
1// Convert a JavaScript object to a JSON string.
2const obj = { name: "Alice", age: 30, active: true };
3const jsonString = JSON.stringify(obj);
4console.log(jsonString); // {"name":"Alice","age":30,"active":true}
- Dieser Code ist das grundlegendste Beispiel für die Umwandlung eines normalen Objekts in einen JSON-String.
JSON.stringifygibt den String synchron zurück.
Das zweite Argument von JSON.stringify (replacer)
Indem Sie replacer, das zweite Argument von JSON.stringify, angeben, können Sie die Umwandlungsregeln präzise steuern. Hier ein Beispiel, das ein Array verwendet, um nur bestimmte Eigenschaften zu behalten.
1// Use a replacer array to include only specific properties during stringification.
2const user = { id: 1, name: "Bob", password: "secret", role: "admin" };
3const safeJson = JSON.stringify(user, ["id", "name", "role"]);
4console.log(safeJson); // {"id":1,"name":"Bob","role":"admin"}
- In diesem Beispiel wird
passwordausgeschlossen, damit eine sichere Protokollausgabe möglich ist. Das ist nützlich, wenn Sie aus Sicherheitsgründen sensible Informationen entfernen möchten.
Verwendung von replacer als Funktion (zur Wertumwandlung und Filterung)
Wenn Sie mehr Flexibilität benötigen, können Sie eine Funktion bereitstellen, um jeden Schlüssel und Wert zu verarbeiten. Unten finden Sie ein Beispiel, bei dem ein Date als ISO-String beibehalten wird.
1// Use a replacer function to customize serialization.
2const data = { name: "Carol", joined: new Date("2020-01-01T12:00:00Z") };
3const jsonCustom = JSON.stringify(data, (key, value) => {
4 // Convert Date objects to ISO strings explicitly
5 if (this && this[key] instanceof Date) {
6 return this[key].toISOString();
7 }
8 return value;
9});
10console.log(jsonCustom); // {"name":"Carol","joined":"2020-01-01T12:00:00.000Z"}
- Bei einem funktionalen
replacerwerden Schlüssel und Wert übergeben, und der zurückgegebene Wert wird im endgültigen JSON verwendet.thisbezieht sich auf das übergeordnete Objekt und kann daher auch für verschachtelte Umwandlungen verwendet werden.
Grundlagen von JSON.parse()
JSON.parse wandelt einen JSON-String wieder in ein Objekt um. Verwenden Sie try/catch, um ungültiges JSON behandeln zu können.
1// Parse a JSON string into an object and handle parsing errors.
2const jsonText = '{"title":"Example","count":42}';
3try {
4 const parsed = JSON.parse(jsonText);
5 console.log(parsed.title); // Example
6} catch (err) {
7 console.error("Invalid JSON:", err.message);
8}- Ist der String ungültig, wird eine Ausnahme ausgelöst – daher sollten Sie beim Umgang mit externen Quellen immer eine Fehlerbehandlung vorsehen.
Individuelle Wiederherstellung mit reviver (Beispiel zum Wiederherstellen von Date)
Mit dem zweiten Argument reviver von JSON.parse können Sie Werte wiederherstellen. Hier ein Beispiel, wie ein gespeichertes Datums-String wieder in ein Date-Objekt umgewandelt wird.
1// Use a reviver to turn ISO date strings back into Date objects.
2const jsonWithDate = '{"name":"Dana","joined":"2021-06-15T09:00:00.000Z"}';
3const obj = JSON.parse(jsonWithDate, (key, value) => {
4 // A simple check for ISO date-like strings
5 if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$/.test(value)) {
6 return new Date(value);
7 }
8 return value;
9});
10console.log(obj.joined instanceof Date); // true
reviverwird für jeden Schlüssel aufgerufen und der zurückgegebene Wert wird im endgültigen Objekt verwendet. Führen Sie eine strikte Prüfung des Datumsformats entsprechend Ihrer Anwendung durch.
Schönformatierung und das Argument space
Um eine eingerückte und besser lesbare Ausgabe zu erhalten, übergeben Sie eine Zahl oder einen String als drittes Argument an JSON.stringify.
1// Pretty-print an object with 2-space indentation for readability.
2const config = { host: "localhost", port: 3000, debug: true };
3const pretty = JSON.stringify(config, null, 2);
4console.log(pretty);
5/* {
6 "host": "localhost",
7 "port": 3000,
8 "debug": true
9} */- Bei für Menschen lesbarem JSON, etwa für Protokolle oder Konfigurationsdateien, ist das Angeben von Einrückungen hilfreich. Beachten Sie jedoch, dass dies die Dateigröße erhöht.
Umgang mit zirkulären Verweisen
JSON.stringify löst einen TypeError aus, wenn ein zirkulärer Verweis vorhanden ist. Eine gängige Lösung ist, mithilfe eines seen-Sets einen replacer zu erstellen, um zirkuläre Verweise zu vermeiden.
1// Safely stringify objects that may contain circular references.
2function safeStringify(value) {
3 const seen = new WeakSet();
4 return JSON.stringify(value, (key, val) => {
5 if (val && typeof val === "object") {
6 if (seen.has(val)) return "[Circular]";
7 seen.add(val);
8 }
9 return val;
10 });
11}
12
13const a = { name: "A" };
14a.self = a;
15console.log(safeStringify(a)); // {"name":"A","self":"[Circular]"}
- Mit einem
WeakSetkönnen Sie zirkuläre Verweise erkennen und gleichzeitig Speicherlecks vermeiden. Bei einem zirkulären Verweis wird"[Circular]"zurückgegeben. Es ist auch möglich, statt"[Circular]"eine Referenz-ID zuzuweisen.
Eigene Serialisierung mit der Methode toJSON
Wenn Sie auf einem Objekt eine toJSON-Methode definieren, verwendet JSON.stringify deren Rückgabewert. Das ist nützlich, wenn Sie Umwandlungsregeln pro Typ einbetten möchten.
1// Define toJSON on a class to customize its JSON representation.
2class Point {
3 constructor(x, y) {
4 this.x = x;
5 this.y = y;
6 }
7 toJSON() {
8 // This will be used by JSON.stringify
9 return { x: this.x, y: this.y, type: "Point" };
10 }
11}
12
13const p = new Point(10, 20);
14console.log(JSON.stringify(p)); // {"x":10,"y":20,"type":"Point"}
toJSONermöglicht es, Serialisierungsregeln auf Objektebene zu definieren, was lokaler und intuitiver als mitreplacerist.
Einschränkungen und Hinweise bei JSON
Beachtenswerte Beispiele, die nicht in JSON umgewandelt werden können, sind undefined, Funktionen, Symbol, BigInt und zirkuläre Verweise. Beachten Sie auch die numerische Genauigkeit (z. B. große Ganzzahlen und Rundung nach IEEE-Gleitkommastandard).
1// Demonstrate values that can't be represented in JSON.
2const sample = {
3 a: undefined,
4 b: function () {},
5 c: Symbol("s"),
6 d: 9007199254740993n // BigInt (note: JSON.stringify will throw on BigInt)
7};
8// JSON.stringify will throw for BigInt and will drop undefined, functions, symbols in objects.
9try {
10 console.log(JSON.stringify(sample));
11} catch (err) {
12 console.error("Error during stringify:", err.message);
13}- Bei der Verarbeitung von
BigIntsollten Sie es in einen String umwandeln oder die Darstellung über einen eigenenreplacerodertoJSONdefinieren.
Sicherheit (beim Umgang mit nicht vertrauenswürdigem JSON)
JSON.parse selbst ist sicherer als eval, aber es ist gefährlich, dem geparsten Objekt zu vertrauen und es direkt für Eigenschaftszugriffe oder Datenbankabfragen zu verwenden. Überprüfen Sie stets, ob die Daten dem erwarteten Schema entsprechen und validieren Sie sie entsprechend.
1// Parse external JSON and validate expected properties before use.
2const external = '{"username":"eve","role":"user"}';
3const parsed = JSON.parse(external);
4if (typeof parsed.username === "string" && ["user","admin"].includes(parsed.role)) {
5 console.log("Safe to use parsed.username and parsed.role.");
6} else {
7 throw new Error("Invalid payload");
8}- Für die Eingabe- bzw. Schema-Validierung ist der Einsatz von Bibliotheken wie
ajvzuverlässig.
Leistungsaspekte
Das häufige (De-)Serialisieren großer Objekte belastet CPU und Arbeitsspeicher. Falls nötig, können Sie nur die Unterschiede versenden, binäre Formate (wie MessagePack) verwenden oder Streaming (sequenzielle Datenverarbeitung) einsetzen. In Browserumgebungen können Sie in manchen Fällen structuredClone (zum Kopieren) oder übertragbare Objekte in postMessage nutzen.
Konkret empfohlene Maßnahmen (kurz)
Sie können außerdem folgende Punkte berücksichtigen:.
- Vermeiden Sie zur Größenersparnis im Protokoll die Schönformatierung und nutzen Sie einzeiliges JSON.
- Objekte, die häufig serialisiert werden, sollten vorher vereinfacht werden, zum Beispiel durch Entfernen unnötiger Eigenschaften.
- Verwenden Sie
replacer, um die Durchläufe zu minimieren und überflüssige Eigenschaften auszuschließen.
Praktisches Beispiel: Ablauf von Versand und Empfang einer API-Anfrage
Abschließend folgt eine Sequenz, wie Sie ein Objekt sicher in JSON konvertieren, um es an einen Server zu senden, und nach Empfang eine Datumsangabe wiederherstellen.
1// Prepare payload, stringify safely, send via fetch, and revive dates on response.
2async function sendUserUpdate(url, user) {
3 // Remove sensitive info before sending
4 const payload = JSON.stringify(user, (k, v) => (k === "password" ? undefined : v));
5 const res = await fetch(url, {
6 method: "POST",
7 headers: { "Content-Type": "application/json" },
8 body: payload
9 });
10
11 const text = await res.text();
12 // Reviver: convert ISO date strings back to Date
13 const data = JSON.parse(text, (key, value) => {
14 if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$/.test(value)) {
15 return new Date(value);
16 }
17 return value;
18 });
19 return data;
20}- In diesem Beispiel wird
passwordvor dem Versand ausgeschlossen und das Datum nach Empfang mit demreviverwiederhergestellt. Im Echtbetrieb müssen Sie Fehlerbehandlung und Timeout-Mechanismen ergänzen.
Zusammenfassung
Mit JSON.stringify() und JSON.parse() können Sie zwischen Objekten und Strings konvertieren. Sie können den Konvertierungsprozess mit replacer und reviver anpassen und durch Implementieren von toJSON in einer Klasse auch jedes Objekt individuell steuern. Zirkuläre Verweise, BigInt, Funktionen usw. können nicht direkt verarbeitet werden und müssen daher vorher behandelt werden.
Validieren Sie stets externe Eingaben und stellen Sie sicher, dass keine sensiblen Informationen in Protokollen oder der Kommunikation enthalten sind. Bei großen Datenmengen ist es effizient, auf Formatierungen zu verzichten, differenzielle Übertragungen zu erwägen oder binäre Formate zu nutzen.
Sie können den obigen Artikel mit Visual Studio Code auf unserem YouTube-Kanal verfolgen. Bitte schauen Sie sich auch den YouTube-Kanal an.