Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Робота з JSON: stringify і parse». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`JSON.stringify()` перетворює об'єкт або масив JavaScript на рядок формату JSON, а `JSON.parse()` робить зворотне: розбирає JSON-рядок назад в об'єкт.** Під час серіалізації функції, `undefined` і `Symbol` просто зникають, а невалідний вхід у `JSON.parse()` кидає `SyntaxError`. Другий і третій аргументи `stringify` (replacer і кількість пробілів) дають фільтрацію та форматування. ```javascript const user = { name: 'Maria' }; const json = JSON.stringify(user); // '{"name":"Maria"}' const obj = JSON.parse(json); // { name: 'Maria' } ``` **Ключове:** `stringify`, це об'єкт у рядок, `parse`, це рядок в об'єкт; пара `JSON.parse(JSON.stringify(obj))` дає швидку глибоку копію, але лише для простих даних.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**`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-рядків ненадійно.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.