Узнайте, как использовать JSON.stringify() для сериализации ошибок

JSON
Узнайте, как использовать JSON.stringify() для сериализации ошибок

Недавно, когда я работал над требованиями к серверу Node, я столкнулся с несколькими ошибками на стороне сервера. Когда я вхожу в систему, я обнаруживаю, что есть некоторые ошибки, но ни одна из них не может быть прозрачно передана во внешний браузер.Если есть проблема, вы можете просмотреть только журнал серверной машины, что очень неудобно для отлаживать. Подумав об этом, содержимое сервера обрабатывается через JSON.stringify(), а затем устанавливаетсяContent-type: text/jsonЗаголовок ответа будет передан во внешний интерфейс позже.Если Error также можно обработать таким образом, его будет намного проще отлаживать.

Например

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

Сначала посмотрите на пример:

const err = new Error('This is an error')
JSON.stringify(err)

// => "{}"

После запуска приведенного выше кода в консоли вы обнаружите, что результатом JSON.stringify() является строка"{}", который не имеет действительного содержимого. Означает ли это, что JSON.stringify() действительно не может обрабатывать Error? Давайте посмотрим, как эта функция определена в MDN.

Определение MDN

Первый взглядописывать

JSON.stringify() преобразует значение в соответствующий формат JSON:

  • Преобразование значений Если есть метод toJSON(), этот метод определяет, какое значение будет сериализовано.
  • Не гарантируется, что свойства объектов, не являющихся массивами, появятся в сериализованной строке в определенном порядке.
  • Булевы, числовые и строковые объекты-обертки автоматически преобразуются в соответствующие примитивные значения во время сериализации.
  • неопределенные, произвольные функции и значения символов игнорируются при сериализации (при наличии в значениях свойств объектов, не являющихся массивами) или преобразуются в null (при наличии в массивах). Когда function и undefined конвертируются по отдельности, будет возвращено undefined, например JSON.stringify(function(){}) или JSON.stringify(undefined).
  • Выполнение этого метода для объектов, содержащих циклические ссылки (объекты, ссылающиеся друг на друга, образующие бесконечный цикл), вызовет ошибку.
  • Все свойства с символом в качестве ключа свойства будут полностью проигнорированы, даже если их принудительно включить в параметр-заменитель.
  • Date вызывает toJSON(), чтобы преобразовать его в строку (так же, как Date.toISOString()), поэтому он будет рассматриваться как строка.
  • Числовые значения и нули в форматах NaN и Infinity обрабатываются как нули.
  • Другие типы объектов, включая Map/Set/weakMap/weakSet, будут сериализовать только перечисляемые свойства.

Есть так много столбцов, чтобы составить количество слов.Мы смотрим только на последнее описание:

Другие типы объектов, включая Map/Set/weakMap/weakSet, будут сериализовать только перечисляемые свойства.

"Только перечисляемые свойства будут сериализованы", что это значит? Как мы все знаем, в мире JS все является объектом, а объекты имеют разные свойства, можно ли перечислить эти свойства, мы используем enumerable для определения.

перечисление свойств объекта

Например, мы используемobj = { a: 1, b: 2, c: 3 }определить объект, а затем установить егоcСвойство «неперечислимое» и посмотрите, как оно работает:

Сначала посмотрите на эффект перед обработкой:

const obj = { a: 1, b: 2, c: 3 }
JSON.stringify(obj)

// => "{"a":1,"b":2,"c":3}"

Посмотрите на эффект после обработки:

const obj = { a: 1, b: 2, c: 3 }

Object.defineProperty(obj, 'c', {
  value: 3,
  enumerable: false
})

JSON.stringify(obj)

// => "{"a":1,"b":2}"

Видно, что вcКак только для свойства установлено значение non-enumerable, JSON.stringify() больше не будет сериализовать его.

Давайте копнем немного глубже, есть ли способ получить все свойства объекта, которые не являются перечисляемыми? Ответ заключается в использованииObject.getOwnPropertyNames()метод.

Еще только переделалиobjобъект, давайте посмотрим на все свойства, которые он содержит:

Object.getOwnPropertyNames(obj)

// => ["a", "b", "c"]

неисчислимыйcАтрибуты также приобретаются!

Таким же образом посмотрим, какие атрибуты содержит ошибка:

const err = new Error('This is an error')
Object.getOwnPropertyNames(err)

// => ["stack", "message"]

Как видите, ошибка содержитstackа такжеmessageдва свойства, оба из которых могут использовать оператор точки.отerrполученный в примере.

Теперь, когда мы смогли получить неперечислимые свойства экземпляра Error и его содержимого, мы не так уж далеки от сериализации Error с помощью JSON.stringify()!

Второй параметр JSON.stringify()

JSON.stringify() может принимать три параметра:

грамматика

JSON.stringify(value[, replacer [, space]])

value

Значение, которое будет сериализовано в строку JSON.

заменитель необязательный

Если параметр является функцией, во время сериализации каждое свойство сериализованного значения будет преобразовано и обработано функцией; если параметр является массивом, только имена свойств, содержащихся в массиве, будут сериализованы в окончательную строку JSON; если этот параметр имеет значение null или не указан, все свойства объекта будут сериализованы.

пробел необязательный

Указывает строку пробелов для отступа, используемого для красивого вывода; если параметр является числом, он представляет количество пробелов; верхний предел равен 10. Если значение меньше 1, это означает отсутствие пробелов; если параметр является строкой (первые десять букв строки), строка будет считаться пробелом; если параметр не указан (или равен нулю) не будет пробелов. Возвращаемое значение Раздел Строка JSON, представляющая заданное значение.

Давайте посмотримreplacerПрименение:

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

по-прежнему использовать вышеobjНапример:

const obj = { a: 1, b: 2, c: 3 }

Object.defineProperty(obj, 'c', {
  value: 3,
  enumerable: false
})

JSON.stringify(obj, ['a', 'c'])

// => "{"a":1,"c":3}"

Как видите, мыreplacerуказывается для сериализации вaа такжеcатрибут, выходным результатом является только значение этих двух атрибутов, и его нельзя перечислить.cСвойства тоже сериализуются! Держа облако открытым и видя луну, выйдет метод сериализации объекта Error:

const err = new Error('This is an error')

JSON.stringify(err, Object.getOwnPropertyNames(err), 2)

// => 
// "{
//   "stack": "Error: This is an error\n    at <anonymous>:1:13",
//   "message": "This is an error"
// }"

постскриптум

Первоначальное название статьи было "You Don't Know JSON.stringify()", но мне всегда казалось, что слова не выразительны, и это подозревалось в заголовке, поэтому я изменил его на более реалистичное название. .

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