Menu
Русский

JSON в JavaScript: JSON.stringify и JSON.parse

Разбираем работу с JSON в JavaScript: как превратить объект в строку через JSON.stringify и обратно через JSON.parse, зачем нужны replacer и reviver, и какие значения теряются при сериализации.

JSON — это текст, а не объект

JSON (JavaScript Object Notation) — это текстовый формат для обмена данными. Внешне он напоминает литерал объекта JavaScript, но на деле это обычная строка — набор символов, который можно передать по сети, сохранить в файл или вставить в конфиг.

// Объект JavaScript — живое значение в памяти.
const user = { name: "Rosa", age: 30 };

// JSON — текстовая строка, представляющая те же данные.
const json = '{"name":"Rosa","age":30}';

Их легко перепутать — уж больно похожи. Держите в голове простую модель: объекты живут внутри вашей программы, а JSON — это то, во что они превращаются, когда уходят наружу. Переключаться между ними помогают две функции: JSON.stringify (объект → строка) и JSON.parse (строка → объект).

JSON.stringify: преобразовать объект в JSON

Превращаем любое значение JavaScript в его JSON-представление:

index.js
Output
Click Run to see the output here.

Результат — однострочная строка без пробелов: компактно и удобно для передачи по сети. Проверка через typeof это подтверждает: string, а не object.

Чтобы было удобнее читать во время отладки, передайте два дополнительных аргумента. Второй — это replacer (о нём чуть позже); null означает «включить всё». Третий отвечает за отступы:

index.js
Output
Click Run to see the output here.

Это стандартный вариант «красивого» вывода. Используйте 2 или 4 пробела — именно так форматирует большинство инструментов.

JSON.parse: из строки в объект

Обратная операция: парсинг JSON-строки обратно в значение JavaScript.

index.js
Output
Click Run to see the output here.

После парсинга вы работаете с обычным объектом JavaScript — точечная нотация, квадратные скобки, методы массивов, всё как всегда.

А вот JSON.parse — штука придирчивая. Все следующие примеры выбросят SyntaxError:

JSON.parse("{name: 'Rosa'}");      // ключ без кавычек, одинарные кавычки
JSON.parse('{"name": "Rosa",}');   // завершающая запятая
JSON.parse("// a comment\n{}");    // комментарии не допускаются
JSON.parse("");                    // пустая строка

Всегда, когда данные приходят извне вашей программы — из ответа fetch, из файла или от пользователя — оборачивайте парсинг в try/catch:

index.js
Output
Click Run to see the output here.

Значения, которые не переживут сериализацию

JSON поддерживает шесть типов значений: строки, числа, булевы значения, null, массивы и обычные объекты. Всё остальное в JavaScript либо выбрасывается, либо превращается во что-то другое, либо ломает сериализацию.

index.js
Output
Click Run to see the output here.

Что происходит на самом деле:

  • Функции и undefined молча выбрасываются из объектов. Внутри массивов они превращаются в null — пропусков в JSON быть не может.
  • Date сериализуется в ISO-строку через метод toJSON. После JSON.parse вы получите обычную строку, а не объект Date.
  • BigInt кидает TypeError. В JSON просто нет подходящего типа для таких чисел.
  • Map, Set и циклические ссылки тоже из коробки не работают.

Чтобы корректно восстановить Date при парсинге, пригодится функция reviver в JSON.parse:

index.js
Output
Click Run to see the output here.

Функция reviver вызывается для каждой пары ключ-значение и даёт возможность трансформировать значения на лету.

Replacer: фильтруем то, что попадёт в JSON

Второй аргумент JSON.stringify позволяет контролировать, что именно окажется в итоговой строке. Передайте массив ключей — и в результат попадут только они:

index.js
Output
Click Run to see the output here.

Либо передайте функцию и крутите логику как угодно — выкидывайте поля, маскируйте значения, преобразуйте на лету:

index.js
Output
Click Run to see the output here.

Если вернуть undefined, ключ будет выброшен из результата. Любое другое возвращённое значение заменит исходное.

Своя сериализация через toJSON

Если у объекта есть метод toJSON, то JSON.stringify вызовет его и засериализует то, что он вернёт, а не сам объект. Именно так Date задаёт свой собственный формат вывода — и вы можете воспользоваться тем же приёмом у себя:

index.js
Output
Click Run to see the output here.

Отлично подходит для классов, у которых должна быть единая публичная форма независимо от того, кто их сериализует.

Глубокое клонирование: старый трюк и тот, что получше

Годами связка JSON.parse(JSON.stringify(obj)) была коронным однострочником для глубокого клонирования обычного объекта:

index.js
Output
Click Run to see the output here.

Работает — но только пока объект содержит значения, совместимые с JSON. Даты, Map-ы и функции всё ломают (выше уже разбирали проблемы с таким «туда-обратно»).

В современном JavaScript есть structuredClone — он корректно обрабатывает даты, Map, Set, типизированные массивы и даже циклические ссылки:

index.js
Output
Click Run to see the output here.

По возможности используйте structuredClone. А приём с JSON.parse(JSON.stringify(...)) держите про запас — для быстрого клонирования простых данных, когда не хочется заморачиваться.

Реальный пример: получение и парсинг JSON

Чаще всего с JSON в JavaScript вы столкнётесь при работе с HTTP. При этом fetch сам по себе JSON не парсит — нужно вызвать .json() у ответа (под капотом это тот же JSON.parse, только применённый к телу ответа):

index.js
Output
Click Run to see the output here.

Отправка JSON — обратная операция: прогоняем тело через JSON.stringify и выставляем заголовок Content-Type.

await fetch("/api/users", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ name: "Rosa", age: 30 }),
});

Этих двух паттернов хватает, чтобы покрыть подавляющую часть реальных задач с JSON.

Дальше: опциональная цепочка

После парсинга JSON часто попадаются необязательные поля — какой-нибудь user.address.city, которого может и не быть, или response.data.items, который иногда просто отсутствует. Чтобы лезть во вложенные свойства и не ловить ошибку, существует опциональная цепочка (?.) — о ней и пойдёт речь на следующей странице.

Часто задаваемые вопросы

Чем JSON отличается от объекта JavaScript?

JSON — это текстовый формат, то есть строка, которая внешне похожа на литерал объекта JavaScript, но с более строгими правилами. Ключи обязательно в двойных кавычках, строки тоже только в двойных кавычках, а из значений допускаются строки, числа, булевы, null, массивы и обычные объекты. Объект JavaScript — это живое значение в памяти, в нём могут лежать функции, undefined, экземпляры Date и вообще что угодно.

Как превратить объект JavaScript в JSON?

Вызываем JSON.stringify(obj) — метод обходит объект и возвращает JSON-строку. Если нужен читаемый вид с отступами, передаём третий аргумент: JSON.stringify(obj, null, 2) даст форматирование с отступом в 2 пробела. Важный момент: функции и значения undefined из объектов просто выкидываются, а внутри массивов превращаются в null.

Почему JSON.parse бросает ошибку?

JSON.parse работает строго по спецификации: висячие запятые, одинарные кавычки, ключи без кавычек и комментарии — всё это приводит к SyntaxError. Поэтому, когда строка приходит из сети, из файла или от пользователя (то есть везде, где JSON может оказаться невалидным), оборачивайте вызов в try/catch.

Сохраняет ли JSON.stringify объекты Date?

Нет. Date превращается в ISO-строку вида "2026-01-15T10:30:00.000Z". Когда вы потом сделаете JSON.parse, вы получите обратно строку, а не объект Date. Если нужны именно даты, используйте второй аргумент JSON.parse — функцию reviver, которая преобразует ISO-строки обратно в Date.

Учитесь программировать с Coddy

НАЧАТЬ