Skip to main content

Робота з 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)), це популярний прийом глибокого копіювання простих структур.

Швидкий приклад

javascript
const user = { name: 'Maria' }; const json = JSON.stringify(user); // '{"name":"Maria"}' const obj = JSON.parse(json); // { name: 'Maria' }

Нагадаємо, що таке JSON: текстовий формат обміну даними, схожий на об'єкти JavaScript, але призначений для зберігання та передавання.

javascript
{ "name": "Maria", "age": 25, "isAdmin": false }

JSON.stringify(): об'єкт у рядок

Метод перетворює об'єкт JavaScript на рядок формату JSON.

javascript
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:

javascript
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

Результат можна гарно відформатувати відступами:

javascript
const json = JSON.stringify(user, null, 2); console.log(json); /* { "name": "Maria", "age": 25, "isAdmin": false } */

Другий аргумент, це replacer, третій, це кількість пробілів для форматування. Як replacer можна передати масив ключів, які треба залишити, або функцію, що обробляє кожну пару ключ-значення:

javascript
JSON.stringify(user, ['name']); // '{"name":"Maria"}' JSON.stringify(user, (key, value) => key === 'age' ? undefined : value); // поле age буде пропущене

Якщо в об'єкта є метод toJSON(), stringify викличе саме його. Тому Date серіалізується у рядок ISO.

JSON.parse(): рядок в об'єкт

Метод перетворює JSON-рядок назад на об'єкт JavaScript.

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"

Якщо рядок невалідний, буде помилка:

javascript
JSON.parse("{name:'Maria'}"); // SyntaxError: Unexpected token n

Правильний варіант:

javascript
JSON.parse('{"name":"Maria"}');

У JSON ключі та рядки завжди мають бути в подвійних лапках " ". Через це будь-який виклик JSON.parse() для даних із мережі варто загортати в try/catch.

JSON.parse() теж має другий аргумент, reviver: функцію, що перетворює кожне значення під час розбору, наприклад повертає Date замість рядка.

Приклад «у зв'язці»

Часто ці методи використовують разом, щоб зберегти дані:

javascript
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 вміє зберігати лише рядки.

Глибоке копіювання об'єкта

javascript
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-рядків ненадійно.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.