JSON.stringify()
Базовый уровень Широко доступно
Эта функция хорошо зарекомендовала себя и работает на многих устройствах и версиях браузеров. Она доступна во всех браузерах с июля 2015 года.
Статический метод JSON.stringify() преобразует значение JavaScript в строку JSON, опционально заменяя значения, если указана функция-заменитель (replacer), или опционально включая только указанные свойства, если указан массив-заменитель.
Попробовать
console.log(JSON.stringify({ x: 5, y: 6 }));
// Expected output: '{"x":5,"y":6}'
console.log(
JSON.stringify([new Number(3), new String("false"), new Boolean(false)]),
);
// Expected output: '[3,"false",false]'
console.log(JSON.stringify({ x: [10, undefined, function () {}, Symbol("")] }));
// Expected output: '{"x":[10,null,null,null]}'
console.log(JSON.stringify(new Date(2006, 0, 2, 15, 4, 5)));
// Expected output: '"2006-01-02T15:04:05.000Z"'
Синтаксис
JSON.stringify(value) JSON.stringify(value, replacer) JSON.stringify(value, replacer, space)
Параметры
-
value - Значение для преобразования в строку JSON.
-
replacerНеобязательно - Функция, изменяющая поведение процесса преобразования в строку (stringification), или массив строк и чисел, который указывает свойства
value, которые должны быть включены в вывод. Еслиreplacerявляется массивом, все элементы в этом массиве, которые не являются строками или числами (будь то примитивы или объекты-оболочки), включая значенияSymbol, полностью игнорируются. Еслиreplacerявляется чем-либо, кроме функции или массива (например,nullили не предоставлен), все свойства объекта с ключами-строками включаются в результирующую строку JSON. -
spaceНеобязательно -
Строка или число, используемое для вставки пробельных символов (включая отступы, символы перевода строки и т.д.) в выходную строку JSON для улучшения читаемости.
Если это число, оно указывает количество пробельных символов, которое будет использоваться в качестве отступа, ограниченное 10 (то есть любое число, большее
10, обрабатывается как10). Значения меньше 1 указывают, что пробельные символы использоваться не должны.Если это строка, эта строка (или первые 10 символов строки, если она длиннее) вставляется перед каждым вложенным объектом или массивом.
Если
spaceявляется чем-либо, кроме строки или числа (может быть как примитивом, так и объектом-оболочкой) — например, являетсяnullили не предоставлен — пробельные символы не используются.
Возвращаемое значение
Строка JSON, представляющая заданное значение, или undefined.
Исключения
-
TypeError - Выбрасывается в одном из следующих случаев:
-
valueсодержит циклическую ссылку. - Обнаружено значение
BigInt.
-
Описание
JSON.stringify() преобразует значение в нотацию JSON, которую оно представляет. Значения преобразуются в строку следующим образом:
-
Объекты
Boolean,Number,StringиBigInt(получаемые черезObject()) преобразуются в соответствующие примитивные значения во время преобразования в строку, в соответствии с традиционной семантикой преобразования. ОбъектыSymbol(получаемые черезObject()) обрабатываются как простые объекты. - Попытка сериализовать значения
BigIntприведет к ошибке. Однако, если BigInt имеет методtoJSON()(через "обезьянье патчирование":BigInt.prototype.toJSON = ...), этот метод может предоставить результат сериализации. Это ограничение гарантирует, что надлежащее поведение сериализации (и, вероятно, сопровождающей ее десериализации) всегда явно предоставляется пользователем. -
Значения
undefined,FunctionиSymbolне являются допустимыми значениями JSON. Если какие-либо такие значения встречаются во время преобразования, они либо опускаются (если находятся в объекте), либо изменяются наnull(если находятся в массиве).JSON.stringify()может вернутьundefinedпри передаче «чистых» значений, таких какJSON.stringify(() => {})илиJSON.stringify(undefined). - Числа
InfinityиNaN, а также значениеnull, все считаютсяnull. (Но в отличие от значений в предыдущем пункте, они никогда не будут опущены.) - Массивы сериализуются как массивы (заключенные в квадратные скобки). Сериализуются только индексы массива между 0 и
length - 1(включительно); другие свойства игнорируются. - Специальный "сырой" объект JSON, созданный с помощью
JSON.rawJSON(), сериализуется как содержащийся в нем необработанный текст JSON (путем доступа к его свойствуrawJSON). - Для других объектов:
-
Все свойства с ключами
Symbolбудут полностью проигнорированы, даже при использовании параметраreplacer. - Если значение имеет метод
toJSON(), он отвечает за определение того, какие данные будут сериализованы. Вместо сериализации объекта будет сериализовано значение, возвращаемое методомtoJSON()при вызове.JSON.stringify()вызываетtoJSONс одним параметром,key, который имеет ту же семантику, что и параметрkeyфункцииreplacer:- если этот объект является значением свойства, то имя свойства
- если он находится в массиве, то индекс в массиве в виде строки
- если
JSON.stringify()был вызван непосредственно для этого объекта, то пустая строка
Все объекты
Temporalреализуют методtoJSON(), который возвращает строку (то же самое, что и вызовtoString()). Таким образом, они будут сериализованы как строки. Аналогично, объектыDateреализуютtoJSON(), который возвращает то же самое, что иtoISOString(). -
Посещаются только перечисляемые собственные свойства. Это означает, что
Map,Setи т. д. станут"{}". Вы можете использовать параметрreplacerдля их сериализации во что-то более полезное.Свойства посещаются с использованием того же алгоритма, что и в
Object.keys(), который имеет четко определенный порядок и стабилен для разных реализаций. Например,JSON.stringifyдля одного и того же объекта всегда будет производить одну и ту же строку, аJSON.parse(JSON.stringify(obj))будет производить объект с тем же порядком ключей, что и исходный (при условии, что объект полностью сериализуем в JSON).
-
Параметр replacer
Параметр replacer может быть либо функцией, либо массивом.
Как массив, его элементы указывают имена свойств в объекте, которые должны быть включены в результирующую строку JSON. Учитываются только строковые и числовые значения; символьные ключи игнорируются.
Как функция, она принимает два параметра: key и value, преобразуемое в строку. Объект, в котором был найден ключ, предоставляется как контекст this replacer.
Функция replacer также вызывается для исходного объекта, преобразуемого в строку, и в этом случае key является пустой строкой (""). Затем она вызывается для каждого свойства в преобразуемом объекте или массиве. Индексы массива будут предоставлены в строковой форме как key. Текущее значение свойства будет заменено возвращаемым значением replacer для преобразования в строку. Это означает:
- Если вы возвращаете число, строку, логическое значение или
null, это значение напрямую сериализуется и используется как значение свойства. (Возврат BigInt также вызовет ошибку.) - Если вы возвращаете
Function,Symbolилиundefined, свойство не включается в вывод. - Если вы возвращаете любой другой объект, этот объект рекурсивно преобразуется в строку, вызывая функцию
replacerдля каждого свойства.
Примечание: При разборе JSON, сгенерированного функциями replacer, вам, вероятно, потребуется использовать параметр reviver для выполнения обратной операции.
Обычно индекс элементов массива никогда не сдвигается (даже если элемент является недопустимым значением, например функцией, он станет null вместо того, чтобы быть опущенным). Использование функции replacer позволяет вам контролировать порядок элементов массива, возвращая другой массив.
Параметр space
Параметр space может использоваться для управления интервалами в итоговой строке.
- Если это число, последовательные уровни при преобразовании в строку будут иметь отступ, равный этому числу пробельных символов.
- Если это строка, последовательные уровни будут иметь отступ, равный этой строке.
Каждый уровень отступа никогда не будет длиннее 10. Числовые значения space ограничиваются 10, а строковые значения усекаются до 10 символов.
Примеры
Использование JSON.stringify
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
Использование функции в качестве replacer
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}'
Если вы хотите, чтобы replacer различал исходный объект и ключ с пустым строковым свойством (поскольку оба дадут пустую строку в качестве ключа и потенциально объект в качестве значения), вам придется отслеживать количество итераций (если это не первая итерация, это настоящий ключ с пустой строкой).
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}"
Использование массива в качестве replacer
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
Использование параметра space
Отступ в выводе на один пробел:
console.log(JSON.stringify({ a: 2 }, null, " "));
/*
{
"a": 2
}
*/
Использование символа табуляции имитирует стандартный вид "красивой" печати:
console.log(JSON.stringify({ uno: 1, dos: 2 }, null, "\t"));
/*
{
"uno": 1,
"dos": 2
}
*/
Поведение toJSON()
Определение toJSON() для объекта позволяет переопределить его поведение сериализации.
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'"]'
Проблема с сериализацией циклических ссылок
Поскольку формат JSON не поддерживает ссылки на объекты (хотя существует черновик IETF), будет выброшена ошибка TypeError, если попытаться закодировать объект с циклическими ссылками.
const circularReference = {};
circularReference.myself = circularReference;
// Serializing circular references throws "TypeError: cyclic object value"
JSON.stringify(circularReference);
Чтобы сериализовать циклические ссылки, вы можете использовать библиотеку, которая их поддерживает (например, cycle.js Дугласа Крокфорда), или реализовать решение самостоятельно, что потребует поиска и замены (или удаления) циклических ссылок сериализуемыми значениями.
Если вы используете JSON.stringify() для глубокого копирования объекта, вы можете вместо этого использовать structuredClone(), который поддерживает циклические ссылки. API движка JavaScript для двоичной сериализации, такой как v8.serialize(), также поддерживают циклические ссылки.
Использование JSON.stringify() с localStorage
В случае, когда вы хотите сохранить объект, созданный пользователем, и обеспечить его восстановление даже после закрытия браузера, следующий пример является моделью применимости JSON.stringify():
// 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);
Корректный JSON.stringify()
Движки, реализующие спецификацию корректного JSON.stringify, будут преобразовывать одиночные суррогаты (любая кодовая точка от U+D800 до U+DFFF) в строку с использованием управляющих последовательностей Unicode, а не буквально (выводя одиночные суррогаты). До этого изменения такие строки не могли быть закодированы в корректных UTF-8 или UTF-16:
JSON.stringify("\uD800"); // '"�"'
Но с этим изменением JSON.stringify() представляет одиночные суррогаты, используя управляющие последовательности JSON, которые могут быть закодированы в корректных UTF-8 или UTF-16:
JSON.stringify("\uD800"); // '"\\ud800"'
Это изменение должно быть обратно совместимым, если вы передаете результат JSON.stringify() в API, такие как JSON.parse(), которые принимают любой корректный текст JSON, поскольку они будут рассматривать управляющие последовательности Unicode для одиночных суррогатов как идентичные самим одиночным суррогатам. Только если вы напрямую интерпретируете результат JSON.stringify(), вам нужно осторожно обрабатывать две возможные кодировки этих кодовых точек в JSON.stringify().
Спецификации
Совместимость с браузерами
| Desktop | Mobile | Server | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on iOS | Samsung Internet | WebView Android | WebView on iOS | Bun | Deno | Node.js | |
stringify |
3 |
12 |
3.5 |
10.5 |
4 |
18 |
4 |
11 |
4 |
1.0 |
4.4 |
4 |
1.0.0 |
1.0 |
0.10.0 |
well_formed_stringify |
72 |
79 |
64 |
60 |
12.1 |
72 |
64 |
50 |
12.2 |
11.0 |
72 |
12.2 |
1.0.0 |
1.0 |
12.0.0 |
Смотрите также
- Полифилл современного поведения
JSON.stringify(символ, корректный unicode, сырой JSON) вcore-js JSON.parse()JSON.rawJSON()
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify