Переклад не закінчено. Будь ласка, допоможіть перекласти цю статтю з англійської.

Метод JSON.stringify() подає об'єкт чи просту величину як JSON-рядок, певним чином перетворюючи або оминаючи ті чи ті властивості, якщо вказано необов'язковий другий аргумент — функцію або масив replacer.

Синтаксис

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

Параметри

value
Значення, яке слід перетворити на рядок JSON.
replacer Optional
Функція, що змінює значення перед їхнім перетворенням на JSON, або масив рядків та чисел, що окреслюють множину властивостей, які буде включено у створений JSON-рядок. Якщо цей аргумент відсутній чи вказано null, до створеного JSON-рядка потраплять всі наявні властивості об'єкта без змін.
space Optional
Значення типу String або Number що використовується для додавання відступів у JSON задля покращення легкочитності. Якщо вказано число — воно означає кількість пропусків в одному відступі. Якщо передати число більше за 10, буде використано 10. Значення менші за 1 вказують на те що відступи не використовуватимуться. Якщо вказано рядок, то його (або перші 10 символів, якщо він задовгий) буде використано як відступ. Якщо ж параметр не вказано (або null), відступи не додаватимуться.

Вертає

Рядок JSON, створений із вказаного значення.

Винятки

Викидає виняток TypeError ("cyclic object value") у випадку, якщо знайдено циклічне посилання.

Опис

Функція JSON.stringify() перетворює значення на рядок, що містить JSON-запис того значення:

  • Якщо значення має свій метод toJSON(), саме він буде відповідати за дані, що будуть серіалізовані.
  • Об'єкти Boolean, Number та String в типовий спосіб перетворюються на відповідні прості величини;
  • Функцію, undefined або значення типу Symbol під час перетворення буде або вилучено (якщо знайдено в об'єкті), або обернено на null (якщо знайдено в масиві). Метод JSON.stringify також може вертати undefined, якщо йому передано «щирі» величини, як-от JSON.stringify(function(){}) чи JSON.stringify(undefined);
  • Всі властивості, що мають за ключ величину типу Symbol, буде знехтувано, навіть якщо задіяно функцію replacer;
  • Екземпляри Date реалізовують функцію toJSON() шляхом повертання рядку (такого ж, як і date.toISOString()), тому вони будуть вважатись рядками.
  • Такі числа, як Infinity та NaN, так як і об'єкт null будуть вважатися за null.
  • Для всіх інших екземплярів Object, включно з Map, Set, WeakMap та WeakSet будуть серіалізовані лише їх перелічувані поля.
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(2006, 0, 2, 15, 4, 5)) 
// '"2006-01-02T15:04:05.000Z"'

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

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

// Стандартні структури даних
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'
 
// Значення типу Symbol:
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' }, function(k, v) {
  if (typeof k === 'symbol') {
    return 'a symbol';
  }
});
// '{}'

// Неперелічувані властивості:
JSON.stringify( Object.create(null, { x: { value: 'x', enumerable: false }, y: { value: 'y', enumerable: true } }) );
// '{"y":"y"}'

Параметер replacer

Параметр replacer може бути функцією або масивом. Якщо то функція, вона прийматиме два параметри: ключ та значення, яке са́ме перетворюється. Об'єкт, якому належить перетворювана властивість, доступний всередині replacer через this. Спершу функцію буде викликано з порожнім рядком замість ключа й тим об'єктом, який має бути перетворено, а відтак для кожної властивості того об'єкта буде здійснено окремий виклик replacer. Кожен виклик має вертати значення, що належить додати до рядка JSON:

  • Якщо повернути Number, до JSON буде додано текстовий запис числа як значення властивості;
  • Якщо повернути String, до JSON буде додано рядок як значення властивості;
  • Якщо повернути Boolean, до JSON буде додано «true» або «false» як значення властивості;
  • Якщо повернути null, null і буде додано до JSON-рядку.
  • Якщо повернути інший об'єкт або масив, його буде рекурсивно перетворено на JSON в той самий спосіб (викликаючи replacer для кожної його властивості), а тоді додано до JSON як значення властивості (якщо повернутий об'єкт є функцією, до JSON нічого додано не буде);
  • Якщо повернути undefined, властивість не потрапить до JSON.
Заувага: Вилучати елементи масиву за допомогою replacer неможливо — якщо повернути undefined, значення елемента лише обернеться на null.
Note: If you wish the replacer to distinguish an initial object from a key with an empty string property (since both would give the empty string as key and potentially an object as value), you will have to keep track of the iteration count (if it is beyond the first iteration, it is a genuine empty string key).

Приклад із функцією

function replacer(key, value) {
  // Фільтрація властивостей
  if (typeof value === 'string') {
    return undefined;
  }
  return value;
}

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

Приклад із масивом

Якщо replacer являється масивом, його значення позначають імена властивостей вхідного об'єкту, що будуть включені в результат.

 

JSON.stringify(foo, ['week', 'month']);  
// '{"week":45,"month":7}', будуть збережені лише властивості "week" та "month"

Параметер space

Аргумент space може застосовуватись для управління відступами в результуючому рядку. Якщо в якості аргументу дано число, кожен із наступних рівнів серіалізації матиме відступ у вигляді відповідної поданому числу кількості пробілів (але не більше 10). Якщо ж в якості аргументу дано рядок, його і буде використано для виконання відступу (або ж 10 перших символів, якщо сам рядок довший).

JSON.stringify({ a: 1, b: {c: 2} }, null, 3);
// Вертає рядок:
// '{
//    "a": 1,
//    "b": {
//       "c": 2
//    }
// }'

А тут замість пропусків буде вжито символ табуляції:

JSON.stringify({ a: 1, b: {c: 2} }, null, '\t');
// Вертає рядок:
// '{
//     "a": 1,
//     "b": {
//         "c": 2
//     }
// }'

Особливий метод toJSON()

Й хоча методи перетворюваних об'єктів загалом нехтуються, метод з ім'ям toJSON має особливе призначення. Якщо перетворюваний об'єкт має метод toJSON(), його буде викликано, а повернене значення вжито (перетворено на JSON) замість самого об'єкту. JSON.stringify() викликає метод toJSON з одним аргументом:

 

  • якщо цей об'єкт являється значенням властивості, то ім'я властивості;
  • якщо це масив, то рядок із індексом масиву;
  • порожній рядок, якщо JSON.stringify() було викликано прямо на цьому об'єкті

Наприклад:

 

var obj = {
    data: 'data',
    
    toJSON(key){
        if(key)
            return `Тепер я вкладений об'єкт під ключем '${key}'`;
        
        else
            return this;
    }
};

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

JSON.stringify({ obj })
// '{"obj":"Тепер я вкладений об'єкт під ключем 'obj'"}'

JSON.stringify([ obj ])
// '["Тепер я вкладений об'єкт під ключем '0'"]'

Проблема із JSON.stringify() при серіалізації циклічних посилань

Зауважте, що, оскільки JSON format не підтримує об'єктні посилання (хоча є чорновик IETF), при спробі кодування об'єкту із циклічними посиланнями буде отримано TypeError.

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

// Серіалізація циклічного посилання викине "TypeError: cyclic object value"
JSON.stringify(circularReference);

Для виконання серіалізації циклічних посилань ви можете використати бібліотеку, що їх підтримує (зокрема cycle.js від Douglas Crockford), або ж реалізувати рішення самостійно, для чого знадобиться пошук і заміна (або видалення) циклічних посилань на підходящі для серіалізації значення.

Тлумачення отриманого JSON як коду JavaScript

Завважте, що JSON не є точнісінькою підмножиною JavaScript. Два розділювачі (рядка та параграфу) не треба екранувати у JSON, але потрібно у JavaScript. Тож якщо ви маєте намір застосувати функцію eval() або скористатися JSONP, доведеться здійснити невеличкі перетворення:

 

function jsFriendlyJSONStringify (s) {
    return JSON.stringify(s).
        replace(/\u2028/g, '\\u2028').
        replace(/\u2029/g, '\\u2029');
}

var s = {
    a: String.fromCharCode(0x2028),
    b: String.fromCharCode(0x2029)
};
try {
    eval('(' + JSON.stringify(s) + ')');
} catch (e) {
    console.log(e); // "SyntaxError: unterminated string literal"
}

// Якщо ловити виключення не має потреби
eval('(' + jsFriendlyJSONStringify(s) + ')');

// console.log у Firefox знімає екранування Юнікоду, якщо
// виводиться в консоль, тому застосуймо alert
alert(jsFriendlyJSONStringify(s)); // {"a":"\u2028","b":"\u2029"}

Приклад застосування JSON.stringify() із localStorage

У випадку, якщо ви хочете зберегти об'єкт, створений вашим користувачем і дозволити відновити його навіть після закриття браузера, ось наступний приклад із моделлю застосування JSON.stringify():

// Створення зразка JSON
var 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 });

// Конвертація рядка JSON через JSON.stringify()
// далі збереження у localStorage із іменем "session"
localStorage.setItem('session', JSON.stringify(session));

// Приклад, як перетворити рядок, отриманий за допомогою  
// JSON.stringify() і збережений у localStorage назад у JSON-об'єкт
var restoredSession = JSON.parse(localStorage.getItem('session'));

// Тепер змінна restoredSession містить об'єкт, що був раніше збережений
// у localStorage
console.log(restoredSession);

Специфікації

Специфікація Статус Коментар
ECMAScript 5.1 (ECMA-262)
The definition of 'JSON.stringify' in that specification.
Standard Первинне визначення. Запроваджено у JavaScript 1.7.
ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'JSON.stringify' in that specification.
Standard  
ECMAScript Latest Draft (ECMA-262)
The definition of 'JSON.stringify' in that specification.
Draft  

Підтримка веб-переглядачами

FeatureChromeEdgeFirefoxInternet ExplorerOperaSafari
Basic support Yes Yes3.5810.54
FeatureAndroid webviewChrome for AndroidEdge mobileFirefox for AndroidOpera AndroidiOS SafariSamsung Internet
Basic support Yes Yes Yes4 Yes Yes Yes

Див. також

  • JSON.parse()
  • cycle.js – Вводить дві функції: JSON.decycle та JSON.retrocycle. Вони дають можливість кодувати і декодувати циклічні структури і ділянки у розширений і зворотньо сумісний формат JSON.

Мітки документа й учасники

Зробили внесок у цю сторінку: AdriandeCita, asmforce, olehsrh, linevich, tbunyk
Востаннє оновлена: AdriandeCita,