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-представление:
Результат — однострочная строка без пробелов: компактно и удобно для передачи по сети. Проверка через typeof это подтверждает: string, а не object.
Чтобы было удобнее читать во время отладки, передайте два дополнительных аргумента. Второй — это replacer (о нём чуть позже); null означает «включить всё». Третий отвечает за отступы:
Это стандартный вариант «красивого» вывода. Используйте 2 или 4 пробела — именно так форматирует большинство инструментов.
JSON.parse: из строки в объект
Обратная операция: парсинг JSON-строки обратно в значение JavaScript.
После парсинга вы работаете с обычным объектом JavaScript — точечная нотация, квадратные скобки, методы массивов, всё как всегда.
А вот JSON.parse — штука придирчивая. Все следующие примеры выбросят SyntaxError:
JSON.parse("{name: 'Rosa'}"); // ключ без кавычек, одинарные кавычки
JSON.parse('{"name": "Rosa",}'); // завершающая запятая
JSON.parse("// a comment\n{}"); // комментарии не допускаются
JSON.parse(""); // пустая строка
Всегда, когда данные приходят извне вашей программы — из ответа fetch, из файла или от пользователя — оборачивайте парсинг в try/catch:
Значения, которые не переживут сериализацию
JSON поддерживает шесть типов значений: строки, числа, булевы значения, null, массивы и обычные объекты. Всё остальное в JavaScript либо выбрасывается, либо превращается во что-то другое, либо ломает сериализацию.
Что происходит на самом деле:
- Функции и
undefinedмолча выбрасываются из объектов. Внутри массивов они превращаются вnull— пропусков в JSON быть не может. Dateсериализуется в ISO-строку через методtoJSON. ПослеJSON.parseвы получите обычную строку, а не объектDate.BigIntкидаетTypeError. В JSON просто нет подходящего типа для таких чисел.Map,Setи циклические ссылки тоже из коробки не работают.
Чтобы корректно восстановить Date при парсинге, пригодится функция reviver в JSON.parse:
Функция reviver вызывается для каждой пары ключ-значение и даёт возможность трансформировать значения на лету.
Replacer: фильтруем то, что попадёт в JSON
Второй аргумент JSON.stringify позволяет контролировать, что именно окажется в итоговой строке. Передайте массив ключей — и в результат попадут только они:
Либо передайте функцию и крутите логику как угодно — выкидывайте поля, маскируйте значения, преобразуйте на лету:
Если вернуть undefined, ключ будет выброшен из результата. Любое другое возвращённое значение заменит исходное.
Своя сериализация через toJSON
Если у объекта есть метод toJSON, то JSON.stringify вызовет его и засериализует то, что он вернёт, а не сам объект. Именно так Date задаёт свой собственный формат вывода — и вы можете воспользоваться тем же приёмом у себя:
Отлично подходит для классов, у которых должна быть единая публичная форма независимо от того, кто их сериализует.
Глубокое клонирование: старый трюк и тот, что получше
Годами связка JSON.parse(JSON.stringify(obj)) была коронным однострочником для глубокого клонирования обычного объекта:
Работает — но только пока объект содержит значения, совместимые с JSON. Даты, Map-ы и функции всё ломают (выше уже разбирали проблемы с таким «туда-обратно»).
В современном JavaScript есть structuredClone — он корректно обрабатывает даты, Map, Set, типизированные массивы и даже циклические ссылки:
По возможности используйте structuredClone. А приём с JSON.parse(JSON.stringify(...)) держите про запас — для быстрого клонирования простых данных, когда не хочется заморачиваться.
Реальный пример: получение и парсинг JSON
Чаще всего с JSON в JavaScript вы столкнётесь при работе с HTTP. При этом fetch сам по себе JSON не парсит — нужно вызвать .json() у ответа (под капотом это тот же JSON.parse, только применённый к телу ответа):
Отправка 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.