Skip to main content
Практика завдань

Json.parse та json.stringify в JavaScript

Що таке JSON?

JSON (JavaScript Object Notation) — текстовий формат для обміну даними, заснований на синтаксисі JavaScript.

JavaScript надає два основні методи для роботи з JSON:

  • JSON.stringify() — перетворення об'єкта в JSON-рядок (серіалізація)
  • JSON.parse() — перетворення JSON-рядка в об'єкт (десеріалізація)

JSON.stringify()

Перетворює значення JavaScript в JSON-рядок.

Основний синтаксис

javascript
JSON.stringify(value, replacer, space)

Параметри

  1. value — значення для перетворення
  2. replacer (необов'язковий) — функція або масив для фільтрації властивостей
  3. space (необов'язковий) — кількість пробілів для форматування

Простий приклад

javascript
const user = { name: 'John', age: 25, isActive: true }; JSON.stringify(user); // '{"name":"John","age":25,"isActive":true}' // З форматуванням JSON.stringify(user, null, 2); /* { "name": "John", "age": 25, "isActive": true } */

Що можна серіалізувати?

Підтримувані типи

javascript
// Об'єкти JSON.stringify({ a: 1 }); // '{"a":1}' // Масиви JSON.stringify([1, 2, 3]); // '[1,2,3]' // Рядки JSON.stringify('text'); // '"text"' // Числа JSON.stringify(42); // '42' // Логічні значення JSON.stringify(true); // 'true' // null JSON.stringify(null); // 'null'

Що ігнорується або перетворюється

javascript
const obj = { fn: function() {}, // Функція - ігнорується undef: undefined, // undefined - ігнорується sym: Symbol('id'), // Symbol - ігнорується date: new Date(), // Дата → рядок nan: NaN, // NaN → null infinity: Infinity, // Infinity → null regex: /test/, // RegExp → {} map: new Map([[1, 'one']]), // Map → {} set: new Set([1, 2, 3]) // Set → {} }; JSON.stringify(obj); // '{"date":"2024-01-01T00:00:00.000Z","nan":null,"infinity":null,"regex":{},"map":{},"set":{}}'

Важливо:

undefined, функції та символи:

  • В об'єктах — ігноруються
  • В масивах — стають null
javascript
JSON.stringify([1, undefined, function() {}, 3]); // '[1,null,null,3]'

Параметр replacer

Масив (фільтрація властивостей)

javascript
const user = { name: 'John', age: 25, password: 'secret123', email: 'john@example.com' }; // Серіалізувати лише ім'я та електронну пошту JSON.stringify(user, ['name', 'email']); // '{"name":"John","email":"john@example.com"}'

Функція (перетворення значення)

javascript
const obj = { name: 'John', age: 25, salary: 100000 }; JSON.stringify(obj, (key, value) => { // Сховати зарплату if (key === 'salary') return undefined; // Подвоїти вік if (key === 'age') return value * 2; return value; }); // '{"name":"John","age":50}'

Параметри функції replacer

  • key — ключ пропси (порожній рядок для кореневого об'єкта)
  • value — значення пропси
  • this — батьківський об'єкт
javascript
const data = { a: 1, nested: { b: 2 } }; JSON.stringify(data, function(key, value) { console.log(`key: "${key}", value:`, value); return value; }); // key: "", value: { a: 1, nested: { b: 2 } } ← кореневий об'єкт // key: "a", value: 1 // key: "nested", value: { b: 2 } // key: "b", value: 2

Параметр space (форматування)

javascript
const obj = { name: 'John', age: 25 }; // Число - кількість пробілів JSON.stringify(obj, null, 2); /* { "name": "John", "age": 25 } */ // Рядок - префікс для кожного рівня JSON.stringify(obj, null, '→ '); /* { → "name": "John", → "age": 25 } */

Метод toJSON()

Об'єкти можуть визначати власну поведінку серіалізації через метод toJSON().

javascript
const user = { name: 'John', birthDate: new Date(1998, 5, 15), toJSON() { return { name: this.name, age: new Date().getFullYear() - this.birthDate.getFullYear() }; } }; JSON.stringify(user); // '{"name":"John","age":26}'

Вбудований toJSON в Date

javascript
const date = new Date(); date.toJSON(); // "2024-01-15T12:00:00.000Z" JSON.stringify({ created: date }); // '{"created":"2024-01-15T12:00:00.000Z"}'

Циклічні посилання

javascript
const obj = { name: 'John' }; obj.self = obj; // Циклічне посилання try { JSON.stringify(obj); } catch (error) { console.error(error); // TypeError: Converting circular structure to JSON }

Рішення: Використання WeakSet

javascript
function stringifyWithoutCircular(obj) { const seen = new WeakSet(); return JSON.stringify(obj, (key, value) => { if (typeof value === 'object' && value !== null) { if (seen.has(value)) { return '[Circular]'; } seen.add(value); } return value; }); } const obj = { name: 'John' }; obj.self = obj; stringifyWithoutCircular(obj); // '{"name":"John","self":"[Circular]"}'

JSON.parse()

Перетворює JSON-рядок в значення JavaScript.

Основний синтаксис

javascript
JSON.parse(text, reviver)

Параметри

  1. text — JSON-рядок для парсингу
  2. reviver (необов'язковий) — функція для перетворення значень

Приклади

javascript
JSON.parse('{"name":"John","age":25}'); // { name: 'John', age: 25 } JSON.parse('[1, 2, 3]'); // [1, 2, 3] JSON.parse('true'); // true JSON.parse('null'); // null JSON.parse('"text"'); // "text" JSON.parse('42'); // 42

Параметр reviver

Функція для перетворення значень під час парсингу.

javascript
const json = '{"name":"John","birthDate":"1998-06-15T00:00:00.000Z"}'; const user = JSON.parse(json, (key, value) => { if (key === 'birthDate') { return new Date(value); // Перетворити рядок в Date } return value; }); console.log(user.birthDate instanceof Date); // true

Параметри функції reviver

  • key — ключ пропси
  • value — значення пропси
  • this — батьківський об'єкт

Функція викликається знизу-вгору (від вкладених до кореневих).

javascript
const json = '{"a":1,"nested":{"b":2}}'; JSON.parse(json, (key, value) => { console.log(`key: "${key}", value:`, value); return value; }); // key: "a", value: 1 // key: "b", value: 2 // key: "nested", value: { b: 2 } // key: "", value: { a: 1, nested: { b: 2 } } ← останній

Помилки парсингу

javascript
// Синтаксична помилка try { JSON.parse("{name: 'John'}"); // Ключі повинні бути в лапках } catch (error) { console.error(error); // SyntaxError: Unexpected token n in JSON at position 1 } // Непарне закриття рядка JSON.parse('{"name": "John}'); // SyntaxError // Зайва кома JSON.parse('{"a": 1,}'); // SyntaxError // Дійсний JSON JSON.parse('{"name":"John"}'); // OK

JSON є більш строгим, ніж JavaScript:

  • Ключі повинні бути в подвійних лапках
  • Не можна використовувати зайві коми
  • Тільки подвійні лапки для рядків
  • Без коментарів

Глибоке клонування з JSON

Простий метод клонування

javascript
const original = { name: 'John', address: { city: 'New York' } }; const clone = JSON.parse(JSON.stringify(original)); clone.address.city = 'Boston'; console.log(original.address.city); // 'New York' console.log(clone.address.city); // 'Boston'

Обмеження методу

javascript
const obj = { date: new Date(), fn: () => {}, undef: undefined, map: new Map([[1, 'one']]), set: new Set([1, 2]) }; const clone = JSON.parse(JSON.stringify(obj)); console.log(clone); // { date: '2024-01-15T12:00:00.000Z' } ← Дата стала рядком // fn, undef, map, set — втрачені

Правильне глибоке клонування

Для повного клонування використовуйте structuredClone() (сучасний стандарт):

javascript
const original = { date: new Date(), map: new Map([[1, 'one']]), set: new Set([1, 2]) }; const clone = structuredClone(original); console.log(clone.date instanceof Date); // true console.log(clone.map instanceof Map); // true

Практичні приклади

LocalStorage

javascript
// Збереження const user = { name: 'John', settings: { theme: 'dark' } }; localStorage.setItem('user', JSON.stringify(user)); // Завантаження const loadedUser = JSON.parse(localStorage.getItem('user'));

Запити до API

javascript
fetch('/api/users', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'John', age: 25 }) }) .then(response => response.json()) .then(data => console.log(data));

Порівняння об'єктів

javascript
function deepEqual(obj1, obj2) { return JSON.stringify(obj1) === JSON.stringify(obj2); } deepEqual({ a: 1, b: 2 }, { a: 1, b: 2 }); // true deepEqual({ a: 1, b: 2 }, { b: 2, a: 1 }); // false (порядок ключів має значення)

Увага:

Цей метод працює лише для простих об'єктів і залежить від порядку ключів.


Продуктивність

javascript
const bigObject = { /* 10000 властивостей */ }; console.time('stringify'); const json = JSON.stringify(bigObject); console.timeEnd('stringify'); // ~10ms console.time('parse'); JSON.parse(json); console.timeEnd('parse'); // ~5ms
  • JSON.parse() зазвичай швидший за JSON.stringify()
  • Може бути повільним для великих об'єктів
  • Розгляньте потоки парсерів для величезного JSON

Висновок

JSON.stringify():

  • Серіалізує об'єкти, масиви, примітиви
  • Ігнорує функції, undefined, Symbol
  • Підтримує replacer для фільтрації та перетворення
  • Підтримує space для форматування
  • Може бути налаштований через toJSON()
  • Не працює з циклічними посиланнями

JSON.parse():

  • Парсить дійсний JSON
  • Підтримує reviver для перетворення
  • Більш строгий, ніж JavaScript (лапки, зайві коми)
  • Може викидати SyntaxError

Глибоке клонування через JSON:

  • Простий метод
  • Втрачає функції, Date, Map, Set
  • Використовуйте structuredClone() для повного клонування

На співбесідах:

Звичайні питання:

  • Що втрачається з JSON.stringify()?
  • Як обробити циклічні посилання?
  • Яка різниця між JSON.parse() та eval()?
  • Як зробити глибоке клонування?
  • Що таке replacer і reviver?

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

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

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

Дочитали статтю?
Практика завдань