Start · Sprachen · JavaScript · Referenz · JSON.stringify()

JSON.stringify()

Methode

Die statische Methode <code>JSON.stringify()</code> wandelt einen JavaScript-Wert in einen JSON-String um.

Kategorie: method-property

Signatur

JSON.stringify(value) JSON.stringify(value, replacer) JSON.stringify(value, replacer, space)

Beschreibung

Die statische Methode JSON.stringify() wandelt einen JavaScript-Wert in einen JSON-String um. Optional können Werte durch eine Replacer-Funktion ersetzt oder – falls ein Replacer-Array angegeben ist – nur die dort genannten Eigenschaften einbezogen werden.

JSON.stringify() wandelt einen Wert in die JSON-Notation um, die dieser Wert repräsentiert. Werte werden auf folgende Weise in Strings umgewandelt:

  • Boolean-, Number-, String- und BigInt-Objekte (erhältlich über Object()) werden während der Serialisierung gemäß der traditionellen Konvertierungssemantik in die entsprechenden primitiven Werte umgewandelt. Symbol-Objekte (erhältlich über Object()) werden als einfache Objekte behandelt.
  • Der Versuch, BigInt-Werte zu serialisieren, wirft einen Fehler. Wenn der BigInt jedoch eine toJSON()-Methode besitzt (durch Monkey-Patching: BigInt.prototype.toJSON = ...), kann diese Methode das Serialisierungsergebnis liefern. Diese Einschränkung stellt sicher, dass ein ordnungsgemäßes Serialisierungsverhalten (und sehr wahrscheinlich auch das dazugehörige Deserialisierungsverhalten) stets explizit vom Benutzer bereitgestellt wird.
  • undefined-, Function- und Symbol-Werte sind keine gültigen JSON-Werte. Werden solche Werte während der Konvertierung angetroffen, so werden sie entweder weggelassen (wenn sie in einem Objekt gefunden werden) oder in null umgewandelt (wenn sie in einem Array gefunden werden). JSON.stringify() kann undefined zurückgeben, wenn „reine" Werte wie JSON.stringify(() => {}) oder JSON.stringify(undefined) übergeben werden.
  • Die Zahlen Infinity und NaN sowie der Wert null werden alle als null behandelt. (Aber im Gegensatz zu den Werten des vorigen Punktes werden sie nie weggelassen.)
  • Arrays werden als Arrays serialisiert (in eckige Klammern eingeschlossen). Nur Array-Indizes zwischen 0 und length - 1 (einschließlich) werden serialisiert; andere Eigenschaften werden ignoriert.
  • Das spezielle Roh-JSON-Objekt, das mit JSON.rawJSON() erzeugt wird, wird als der rohe JSON-Text serialisiert, den es enthält (durch Zugriff auf seine rawJSON-Eigenschaft).
  • Für andere Objekte:
    • Alle Eigenschaften mit Symbol-Schlüsseln werden vollständig ignoriert, selbst wenn der replacer-Parameter verwendet wird.
    • Wenn der Wert eine toJSON()-Methode besitzt, ist diese dafür verantwortlich zu definieren, welche Daten serialisiert werden. Statt des Objekts selbst wird der von der toJSON()-Methode zurückgegebene Wert serialisiert. JSON.stringify() ruft toJSON mit einem Parameter auf, dem key, der dieselbe Semantik hat wie der key-Parameter der replacer-Funktion:
      • ist dieses Objekt ein Eigenschaftswert, der Eigenschaftsname
      • befindet es sich in einem Array, der Index im Array als String
      • wurde JSON.stringify() direkt auf diesem Objekt aufgerufen, ein leerer String
      Alle Temporal-Objekte implementieren die toJSON()-Methode, die einen String zurückgibt (dasselbe wie der Aufruf von toString()). Somit werden sie als Strings serialisiert. Ebenso implementieren Date-Objekte toJSON(), das dasselbe zurückgibt wie toISOString().
    • Es werden nur enumerable eigene Eigenschaften besucht. Das bedeutet, dass Map, Set usw. zu "{}" werden. Sie können den replacer-Parameter verwenden, um diese zu etwas Nützlicherem zu serialisieren.

      Eigenschaften werden mit demselben Algorithmus besucht wie bei Object.keys(), welcher eine wohldefinierte und implementierungsübergreifend stabile Reihenfolge hat. Zum Beispiel wird JSON.stringify für dasselbe Objekt stets denselben String erzeugen, und JSON.parse(JSON.stringify(obj)) würde ein Objekt mit derselben Schlüssel-Reihenfolge wie das Original ergeben (vorausgesetzt, das Objekt ist vollständig JSON-serialisierbar).

Der replacer-Parameter

Der replacer-Parameter kann entweder eine Funktion oder ein Array sein.

Als Array geben seine Elemente die Namen der Eigenschaften im Objekt an, die im resultierenden JSON-String enthalten sein sollen. Es werden nur String- und Number-Werte berücksichtigt; Symbol-Schlüssel werden ignoriert.

Als Funktion nimmt er zwei Parameter entgegen: den key und den value, der serialisiert wird. Das Objekt, in dem der Schlüssel gefunden wurde, wird als this-Kontext des replacer bereitgestellt.

Die replacer-Funktion wird auch für das anfängliche zu serialisierende Objekt aufgerufen, wobei der key in diesem Fall ein leerer String ("") ist. Danach wird sie für jede Eigenschaft des zu serialisierenden Objekts oder Arrays aufgerufen. Array-Indizes werden in Stringform als key bereitgestellt. Der aktuelle Eigenschaftswert wird für die Serialisierung durch den Rückgabewert des replacer ersetzt. Das bedeutet:

  • Wenn Sie eine Zahl, einen String, einen Boolean oder null zurückgeben, wird dieser Wert direkt serialisiert und als Wert der Eigenschaft verwendet. (Das Zurückgeben eines BigInt wirft ebenfalls einen Fehler.)
  • Wenn Sie eine Function, ein Symbol oder undefined zurückgeben, wird die Eigenschaft nicht in die Ausgabe aufgenommen.
  • Wenn Sie ein beliebiges anderes Objekt zurückgeben, wird das Objekt rekursiv serialisiert und die replacer-Funktion für jede seiner Eigenschaften aufgerufen.

Normalerweise verschieben sich die Indizes der Array-Elemente nie (selbst wenn das Element ein ungültiger Wert wie eine Funktion ist, wird es zu null, statt weggelassen zu werden). Mit der replacer-Funktion können Sie die Reihenfolge der Array-Elemente steuern, indem Sie ein anderes Array zurückgeben.

Der space-Parameter

Der space-Parameter kann verwendet werden, um die Einrückung im finalen String zu steuern.

  • Wenn er eine Zahl ist, werden aufeinanderfolgende Ebenen der Serialisierung jeweils um so viele Leerzeichen eingerückt.
  • Wenn er ein String ist, werden aufeinanderfolgende Ebenen um diesen String eingerückt.

Jede Einrückungsebene wird nie länger als 10 sein. Zahlenwerte von space werden auf 10 begrenzt, und String-Werte werden auf 10 Zeichen gekürzt.

Parameter

Name Typ Default Beschreibung
$value Pflicht any Der Wert, der in einen JSON-String umgewandelt werden soll.
$replacer Function | Array Eine Funktion, die das Verhalten der Serialisierung verändert, oder ein Array aus Strings und Zahlen, das die Eigenschaften von value angibt, die in die Ausgabe aufgenommen werden sollen. Ist replacer ein Array, werden alle Elemente in diesem Array, die keine Strings oder Zahlen sind (weder primitive noch Wrapper-Objekte), einschließlich Symbol-Werten, vollständig ignoriert. Ist replacer etwas anderes als eine Funktion oder ein Array (z.B. null oder nicht angegeben), werden alle string-basierten Eigenschaften des Objekts in den resultierenden JSON-String aufgenommen.
$space string | number Ein String oder eine Zahl, mit dem/der Leerraum (einschließlich Einrückung, Zeilenumbrüchen usw.) zur besseren Lesbarkeit in den ausgegebenen JSON-String eingefügt wird. Ist dies eine Zahl, gibt sie die Anzahl der Leerzeichen an, die als Einrückung verwendet werden, begrenzt auf 10 (jede Zahl größer als 10 wird wie 10 behandelt). Werte kleiner als 1 bedeuten, dass kein Leerraum verwendet werden soll. Ist dies ein String, wird der String (bzw. die ersten 10 Zeichen davon, wenn er länger ist) vor jedem verschachtelten Objekt oder Array eingefügt. Ist space etwas anderes als ein String oder eine Zahl (kann primitiv oder Wrapper-Objekt sein) — beispielsweise null oder nicht angegeben — wird kein Leerraum verwendet.

Rückgabewert

Typ
string | undefined
Beschreibung
Ein JSON-String, der den gegebenen Wert repräsentiert, oder undefined.

Beispiele

JSON.stringify verwenden

JSON.stringify({}); // '{}'
JSON.stringify(true); // 'true'
JSON.stringify("foo"); // '"foo"'
JSON.stringify([1, "false", false]); // '[1,"false",false]'
JSON.stringify([NaN, null, Infinity]); // '[null,null,null]'
JSON.stringify({ x: 5 }); // '{"x":5}'

JSON.stringify(new Date(1906, 0, 2, 15, 4, 5));
// '"1906-01-02T15:04:05.000Z"'

JSON.stringify({ x: 5, y: 6 });
// '{"x":5,"y":6}'
JSON.stringify([new Number(3), new String("false"), new Boolean(false)]);
// '[3,"false",false]'

// String-keyed array elements are not enumerable and make no sense in JSON
const a = ["foo", "bar"];
a["baz"] = "quux"; // a: [ 0: 'foo', 1: 'bar', baz: 'quux' ]
JSON.stringify(a);
// '["foo","bar"]'

JSON.stringify({ x: [10, undefined, function () {}, Symbol("")] });
// '{"x":[10,null,null,null]}'

// Standard data structures
JSON.stringify([
  new Set([1]),
  new Map([[1, 2]]),
  new WeakSet([{ a: 1 }]),
  new WeakMap([[{ a: 1 }, 2]]),
]);
// '[{},{},{},{}]'

// TypedArray
JSON.stringify([new Int8Array([1]), new Int16Array([1]), new Int32Array([1])]);
// '[{"0":1},{"0":1},{"0":1}]'
JSON.stringify([
  new Uint8Array([1]),
  new Uint8ClampedArray([1]),
  new Uint16Array([1]),
  new Uint32Array([1]),
]);
// '[{"0":1},{"0":1},{"0":1},{"0":1}]'
JSON.stringify([new Float32Array([1]), new Float64Array([1])]);
// '[{"0":1},{"0":1}]'

// toJSON()
JSON.stringify({
  x: 5,
  y: 6,
  toJSON() {
    return this.x + this.y;
  },
});
// '11'

// Symbols:
JSON.stringify({ x: undefined, y: Object, z: Symbol("") });
// '{}'
JSON.stringify({ [Symbol("foo")]: "foo" });
// '{}'
JSON.stringify({ [Symbol.for("foo")]: "foo" }, [Symbol.for("foo")]);
// '{}'
JSON.stringify({ [Symbol.for("foo")]: "foo" }, (k, v) => {
  if (typeof k === "symbol") {
    return "a symbol";
  }
});
// undefined

// Non-enumerable properties:
JSON.stringify(
  Object.create(null, {
    x: { value: "x", enumerable: false },
    y: { value: "y", enumerable: true },
  }),
);
// '{"y":"y"}'

// BigInt values throw
JSON.stringify({ x: 2n });
// TypeError: BigInt value can't be serialized in JSON

Eine Funktion als replacer verwenden

function replacer(key, value) {
  // Filtering out properties
  if (typeof value === "string") {
    return undefined;
  }
  return value;
}

const foo = {
  foundation: "Mozilla",
  model: "box",
  week: 45,
  transport: "car",
  month: 7,
};
JSON.stringify(foo, replacer);
// '{"week":45,"month":7}'

Ersten Aufruf vom leeren Schlüssel unterscheiden

function makeReplacer() {
  let isInitial = true;

  return (key, value) => {
    if (isInitial) {
      isInitial = false;
      return value;
    }
    if (key === "") {
      // Omit all properties with name "" (except the initial object)
      return undefined;
    }
    return value;
  };
}

const replacer = makeReplacer();
console.log(JSON.stringify({ "": 1, b: 2 }, replacer)); // "{"b":2}"

Ein Array als replacer verwenden

const foo = {
  foundation: "Mozilla",
  model: "box",
  week: 45,
  transport: "car",
  month: 7,
};

JSON.stringify(foo, ["week", "month"]);
// '{"week":45,"month":7}', only keep "week" and "month" properties

Den space-Parameter verwenden

console.log(JSON.stringify({ a: 2 }, null, " "));
/*
{
 "a": 2
}
*/

Tabulator als Einrückung

console.log(JSON.stringify({ uno: 1, dos: 2 }, null, "\t"));
/*
{
	"uno": 1,
	"dos": 2
}
*/

toJSON()-Verhalten

const obj = {
  data: "data",

  toJSON(key) {
    return key ? `Now I am a nested object under key '${key}'` : this;
  },
};

JSON.stringify(obj);
// '{"data":"data"}'

JSON.stringify({ obj });
// '{"obj":"Now I am a nested object under key 'obj'"}'

JSON.stringify([obj]);
// '["Now I am a nested object under key '0'"]'

Problem beim Serialisieren zirkulärer Referenzen

const circularReference = {};
circularReference.myself = circularReference;

// Serializing circular references throws "TypeError: cyclic object value"
JSON.stringify(circularReference);

JSON.stringify() mit localStorage verwenden

// Creating an example of JSON
const session = {
  screens: [],
  state: true,
};
session.screens.push({ name: "screenA", width: 450, height: 250 });
session.screens.push({ name: "screenB", width: 650, height: 350 });
session.screens.push({ name: "screenC", width: 750, height: 120 });
session.screens.push({ name: "screenD", width: 250, height: 60 });
session.screens.push({ name: "screenE", width: 390, height: 120 });
session.screens.push({ name: "screenF", width: 1240, height: 650 });

// Converting the JSON string with JSON.stringify()
// then saving with localStorage in the name of session
localStorage.setItem("session", JSON.stringify(session));

// Example of how to transform the String generated through
// JSON.stringify() and saved in localStorage in JSON object again
const restoredSession = JSON.parse(localStorage.getItem("session"));

// Now restoredSession variable contains the object that was saved
// in localStorage
console.log(restoredSession);

Wohlgeformtes JSON.stringify() – vorher

JSON.stringify("\uD800"); // '"�"'

Wohlgeformtes JSON.stringify() – nachher

JSON.stringify("\uD800"); // '"\\ud800"'

// Wichtig · Fallstricke

Wirft einen TypeError, wenn value eine zirkuläre Referenz enthält oder ein BigInt-Wert angetroffen wird. Hinweis: Beim Parsen von JSON, das mit replacer-Funktionen erzeugt wurde, ist es meist sinnvoll, den reviver-Parameter zu verwenden, um die umgekehrte Operation durchzuführen. Für zirkuläre Referenzen kann als Alternative structuredClone() verwendet werden.