Робота з JSON: stringify і parse
JSON.stringify() перетворює дані JavaScript на рядок формату JSON, а JSON.parse() перетворює JSON-рядок назад на дані JavaScript. Це одна з найчастіше вживаних пар методів у мові: вона потрібна скрізь, де дані треба зберегти або передати мережею.
Теорія
TL;DR
JSON.stringify(value), це серіалізація: об'єкт або масив стає рядком.JSON.parse(text), це десеріалізація: рядок стає об'єктом або масивом.stringifyпропускає функції,undefinedіSymbol, а вкладені об'єкти обходить рекурсивно.- Третій аргумент
stringifyзадає відступи:JSON.stringify(obj, null, 2). parseкидаєSyntaxErrorна будь-якому невалідному рядку, тому його загортають уtry/catch.JSON.parse(JSON.stringify(obj)), це популярний прийом глибокого копіювання простих структур.
Швидкий приклад
const user = { name: 'Maria' };
const json = JSON.stringify(user); // '{"name":"Maria"}'
const obj = JSON.parse(json); // { name: 'Maria' }Нагадаємо, що таке JSON: текстовий формат обміну даними, схожий на об'єкти JavaScript, але призначений для зберігання та передавання.
{
"name": "Maria",
"age": 25,
"isAdmin": false
}JSON.stringify(): об'єкт у рядок
Метод перетворює об'єкт JavaScript на рядок формату JSON.
const user = {
name: 'Maria',
age: 25,
isAdmin: false
};
const json = JSON.stringify(user);
console.log(json);
// '{"name":"Maria","age":25,"isAdmin":false}'
console.log(typeof json); // "string"Тепер json, це звичайний рядок, який можна відправити мережею або записати у файл.
Що саме робить JSON.stringify():
- перетворює об'єкт або масив на рядок;
- ігнорує функції,
undefinedі символи (Symbol); - рекурсивно обходить вкладені об'єкти.
Приклад із функцією і undefined:
const data = {
name: 'JS',
greet() { console.log('Hi'); },
test: undefined
};
console.log(JSON.stringify(data));
// '{"name":"JS"}', функції та undefined до JSON не потрапляютьУсередині масиву такі значення не зникають, а замінюються на null: JSON.stringify([1, undefined, () => {}]) дає '[1,null,null]'.
Форматування та replacer
Результат можна гарно відформатувати відступами:
const json = JSON.stringify(user, null, 2);
console.log(json);
/*
{
"name": "Maria",
"age": 25,
"isAdmin": false
}
*/Другий аргумент, це replacer, третій, це кількість пробілів для форматування. Як replacer можна передати масив ключів, які треба залишити, або функцію, що обробляє кожну пару ключ-значення:
JSON.stringify(user, ['name']); // '{"name":"Maria"}'
JSON.stringify(user, (key, value) =>
key === 'age' ? undefined : value); // поле age буде пропущенеЯкщо в об'єкта є метод toJSON(), stringify викличе саме його. Тому Date серіалізується у рядок ISO.
JSON.parse(): рядок в об'єкт
Метод перетворює JSON-рядок назад на об'єкт JavaScript.
const json = '{"name":"Maria","age":25,"isAdmin":false}';
const user = JSON.parse(json);
console.log(user.name); // "Maria"
console.log(user.age); // 25
console.log(typeof user); // "object"Якщо рядок невалідний, буде помилка:
JSON.parse("{name:'Maria'}"); // SyntaxError: Unexpected token nПравильний варіант:
JSON.parse('{"name":"Maria"}');У JSON ключі та рядки завжди мають бути в подвійних лапках " ". Через це будь-який виклик JSON.parse() для даних із мережі варто загортати в try/catch.
JSON.parse() теж має другий аргумент, reviver: функцію, що перетворює кожне значення під час розбору, наприклад повертає Date замість рядка.
Приклад «у зв'язці»
Часто ці методи використовують разом, щоб зберегти дані:
const user = { name: 'Maria', skills: ['JS', 'React'] };
const json = JSON.stringify(user);
localStorage.setItem('user', json); // зберегли рядок
const fromStorage = JSON.parse(localStorage.getItem('user'));
console.log(fromStorage.skills); // ['JS', 'React']Це працює саме тому, що localStorage вміє зберігати лише рядки.
Глибоке копіювання об'єкта
const obj = { a: 1, b: { c: 2 } };
const copy = JSON.parse(JSON.stringify(obj));
copy.b.c = 999;
console.log(obj.b.c); // 2, оригінал не змінивсяЦей прийом часто використовують, щоб зробити глибоку копію без спільних посилань. Він працює лише для простих даних; для решти є вбудований structuredClone(obj).
Підсумкова таблиця
| Метод | Напрямок | Що робить | Результат |
|---|---|---|---|
JSON.stringify() | об'єкт у рядок | перетворює об'єкт JS на JSON-текст | '{"name":"Maria"}' |
JSON.parse() | рядок в об'єкт | перетворює JSON-текст на об'єкт JS | { name: 'Maria' } |
Типові помилки
- Викликати
JSON.parse()безtry/catch. Порожня відповідь сервера або HTML замість JSON валять застосунок винятком. - Очікувати, що всі поля переживуть серіалізацію. Функції,
undefinedіSymbolзникають з об'єкта, а в масиві стаютьnull. - Використовувати
JSON.parse(JSON.stringify(...))для складних структур.Dateстає рядком,Map,SetіRegExpперетворюються на порожні об'єкти, аBigIntкидаєTypeError. - Забувати про циклічні посилання. Об'єкт, який посилається сам на себе, дає
TypeError: Converting circular structure to JSON. - Писати JSON вручну з одинарними лапками або комою в кінці. Такий рядок валідний у JavaScript, але невалідний у JSON.
- Думати, що
JSON.stringify()гарантує порядок ключів як у схемі. Порядок визначається об'єктом, тому порівнювати два об'єкти через порівняння їхніх JSON-рядків ненадійно.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.