Преобразование объекта Error в строку с JSON.stringify

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

JSON.stringify() не может корректно сериализовать объекты Error, так как они содержат неперечислимые свойства. Для решения этой проблемы можно использовать следующий подход:

JS
Скопировать код
const error = new Error('Упс');
const serializedError = JSON.stringify(
  error, 
  Object.getOwnPropertyNames(error)
);

Применение метода Object.getOwnPropertyNames() позволяет учитывать все свойства объекта Error при сериализации.

Кинга Идем в IT: пошаговый план для смены профессии

Понимание процесса сериализации ошибок

Главная сложность при сериализации объектов Error заключается в неперечислимых свойствах, которые JSON.stringify() просто игнорирует. Рассмотрим несколько эффективных подходов к решению этой задачи.

Улучшение сериализации ошибок с помощью метода toJSON

Один из вариантов — добавить метод toJSON в прототип Error. Это упростит процесс сериализации:

JS
Скопировать код
if (!('toJSON' in Error.prototype)) {
  Object.defineProperty(Error.prototype, 'toJSON', {
    value: function () {
      const alt = {};
      Object.getOwnPropertyNames(this).forEach(function (key) {
        alt[key] = this[key]; // Перебираем и "захватываем" каждое свойство
      }, this);
      return alt;
    },
    configurable: true,
    writable: true
  });
}

После такой настройки JSON.stringify способен без проблем сериализовать объекты Error.

Подробнее об этом расскажет наш спикер на видео
skypro youtube speaker

Использование функции-репортера

Другой вариант — использовать функцию-репортер в JSON.stringify для индивидуальной настройки сериализации:

JS
Скопировать код
function replaceErrors(key, value) {
  if (value instanceof Error) {
    let error = {};
    Object.getOwnPropertyNames(value).forEach(function (key) {
      error[key] = value[key]; // "Перехватываем" свойства ошибки
    });
    return error;
  }
  return value;
}

const error = new Error('Что-то пошло не так');
const serializedError = JSON.stringify(
  error, 
  replaceErrors
);

Этот подход успешно борется с проблемой неперечислимых свойств, обеспечивая корректную сериализацию.

Расширенные объекты ошибок

Пользовательские объекты ошибок позволяют добавить дополнительные перечислимые свойства:

JS
Скопировать код
class DetailedError extends Error {
  constructor(message, ...params) {
    super(message, ...params);
    
    if (Error.captureStackTrace) {
      Error.captureStackTrace(this, DetailedError);
    }

    this.name = 'DetailedError';
    this.date = new Date();
    this.customProperty = 'Произвольное значение';
  }
}

const detailedError = new DetailedError('Подробности об ошибке');
const serializedDetailedError = JSON.stringify(detailedError);

Использование внешних библиотек

Если требуется готовое решение, пакет serialize-error с npm поможет выполнить сериализацию ошибок:

JS
Скопировать код
const { serializeError } = require('serialize-error');
const error = new Error('Пример использования');
const serializedError = JSON.stringify(serializeError(error));

Визуализация

Обычно JSON.stringify() может легко преобразовать объекты в JSON-строки:

Markdown
Скопировать код
JSON.stringify({ ... }) // Преобразует объект в полноценную JSON-строку

Но при работе с объектами Error:

JS
Скопировать код
let error = new Error("Таинственная ошибка");
JSON.stringify(error); // Возвращает "{}"

Это кажется загадкой, будто мы столкнулись с недоразумением:

Markdown
Скопировать код
📸 + 👻 = ❓

Детали ошибки, такие как трассировка стека и текст сообщения об ошибке, остаются невидимыми для JSON.stringify, поскольку он не умеет работать с неперечислимыми свойствами.

Расшифровка "невидимых" свойств

Суть проблемы в том, что свойства объектов Error неперечислимы из соображений безопасности, чтобы предотвратить случайное раскрытие конфиденциальной информации.

Осознанная сериализация

Если требуется сериализовать только конкретные свойства, можно использовать функцию фильтрации:

JS
Скопировать код
const error = new Error('Выборочная сериализация');
const selectiveSerializedError = JSON.stringify(
  error, 
  (key, value) => ['name', 'message', 'stack'].includes(key) ? value : undefined
);

Данная функция сохранит только свойства name, message и stack, проигнорировав все остальные.

Обеспечение надёжности сериализации

Перед применением любого метода сериализации важно провести тщательное тестирование. Проверка корректности работы stringifyError и полноты журналов ошибок — ключевые условия для надёжного и эффективного управления исключительными ситуациями.

Полезные материалы

  1. JSON.stringify() – JavaScript | MDNофициальная документация по методу JSON.stringify() в JavaScript.
  2. Невозможно ли сериализовать объект Error с помощью JSON.stringify? – Stack Overflowобсуждение в сообществе о специфике сериализации объектов Error.
  3. API трассировки стека · V8 — анализ API трассировки стека ошибок в V8, полезный источник информации для работы с объектами Error.
  4. ECMAScript® 2019 Language Specificationстандарт ECMA с детальной информацией о JSON.
  5. Ошибки | Документация Node.js v21.6.1 — официальная документация Node.js, объясняющая пользовательскую сериализацию в JSON для ошибок.
Проверь как ты усвоил материалы статьи
Пройди тест и узнай насколько ты лучше других читателей
Почему `JSON.stringify()` не может корректно сериализовать объекты `Error`?
1 / 5