[javascript] JSON.stringify를 사용하여 오류를 문자열화할 수 없습니까?
문제 재현
웹 소켓 사용과 관련된 오류 메시지를 전달하려고 할 때 문제가 발생했습니다. JSON.stringify
더 많은 잠재 고객에게 제공하기 위해 사용중인 문제를 복제 할 수 있습니다 .
// node v0.10.15
> var error = new Error('simple error message');
undefined
> error
[Error: simple error message]
> Object.getOwnPropertyNames(error);
[ 'stack', 'arguments', 'type', 'message' ]
> JSON.stringify(error);
'{}'
문제는 빈 객체로 끝나는 것입니다.
내가 시도한 것
브라우저
먼저 node.js를 떠나 여러 브라우저에서 실행하려고했습니다. Chrome 버전 28은 동일한 결과를 제공하며 흥미롭게도 Firefox는 최소한 시도하지만 메시지를 생략했습니다.
>>> JSON.stringify(error); // Firebug, Firefox 23
{"fileName":"debug eval code","lineNumber":1,"stack":"@debug eval code:1\n"}
대체 기능
그런 다음 Error.prototype 을 살펴 보았습니다 . 프로토 타입에 toString 및 toSource 와 같은 메소드가 포함되어 있음을 보여줍니다 . 함수를 문자열 화 할 수 없다는 것을 알고 JSON.stringify를 호출하여 모든 함수를 제거 할 때 대체 함수를 포함 시켰지만 이상한 동작이 있음을 깨달았습니다.
var error = new Error('simple error message');
JSON.stringify(error, function(key, value) {
console.log(key === ''); // true (?)
console.log(value === error); // true (?)
});
평소와 같이 객체를 반복하는 것처럼 보이지 않으므로 키가 함수인지 확인하고 무시할 수 없습니다.
질문
로 원시 오류 메시지를 문자열 화하는 방법이 JSON.stringify
있습니까? 그렇지 않은 경우 왜이 동작이 발생합니까?
이 문제를 해결하는 방법
- 간단한 문자열 기반 오류 메시지를 고수하거나 개인 오류 개체를 만들고 기본 오류 개체를 사용하지 마십시오.
- 풀 속성 :
JSON.stringify({ message: error.message, stack: error.stack })
업데이트
@Ray Toal 속성 설명자를 살펴 보는 의견에서 제안했습니다 . 왜 작동하지 않는지 분명합니다.
var error = new Error('simple error message');
var propertyNames = Object.getOwnPropertyNames(error);
var descriptor;
for (var property, i = 0, len = propertyNames.length; i < len; ++i) {
property = propertyNames[i];
descriptor = Object.getOwnPropertyDescriptor(error, property);
console.log(property, descriptor);
}
산출:
stack { get: [Function],
set: [Function],
enumerable: false,
configurable: true }
arguments { value: undefined,
writable: true,
enumerable: false,
configurable: true }
type { value: undefined,
writable: true,
enumerable: false,
configurable: true }
message { value: 'simple error message',
writable: true,
enumerable: false,
configurable: true }
키 : enumerable: false
.
허용되는 답변은이 문제에 대한 해결 방법을 제공합니다.
답변
을 정의하여 다음 Error.prototype.toJSON
을 Object
나타내는 일반을 검색 할 수 있습니다 Error
.
if (!('toJSON' in Error.prototype))
Object.defineProperty(Error.prototype, 'toJSON', {
value: function () {
var alt = {};
Object.getOwnPropertyNames(this).forEach(function (key) {
alt[key] = this[key];
}, this);
return alt;
},
configurable: true,
writable: true
});
var error = new Error('testing');
error.detail = 'foo bar';
console.log(JSON.stringify(error));
// {"message":"testing","detail":"foo bar"}
속성 자체 가 아닌 Object.defineProperty()
추가 toJSON
를 사용 합니다 enumerable
.
수정 Error.prototype
에 대해서는 구체적 toJSON()
으로 정의되지 않았지만 방법은 여전히 표준화되어 있습니다.Error
일반적으로 객체에 대해 되어 있습니다 (3 단계 참조). 따라서 충돌 또는 충돌의 위험이 최소화됩니다.
여전히 완전히 피하기 위해 대신에 JSON.stringify()
의 replacer
매개 변수를 사용할 수 있습니다.
function replaceErrors(key, value) {
if (value instanceof Error) {
var error = {};
Object.getOwnPropertyNames(value).forEach(function (key) {
error[key] = value[key];
});
return error;
}
return value;
}
var error = new Error('testing');
error.detail = 'foo bar';
console.log(JSON.stringify(error, replaceErrors));
답변
JSON.stringify(err, Object.getOwnPropertyNames(err))
작동하는 것 같습니다
[ / r / javascript에 대한 / u / ub3rgeek의 의견] 및 felixfbecker의 의견
답변
아무도 이유 에 대해 이야기하지 않기 때문에 부분 대답하겠습니다.
왜 이것이 JSON.stringify
빈 객체를 반환합니까?
> JSON.stringify(error);
'{}'
대답
JSON.stringify () 문서 에서
다른 모든 Object 인스턴스 (Map, Set, WeakMap 및 WeakSet 포함)의 경우 열거 가능한 속성 만 직렬화됩니다.
그리고 Error
객체는 빈 객체를 인쇄 그 이유는, 그 열거 속성이 없습니다.
답변
원숭이 패치를 피하기 위해 Jonathan의 훌륭한 답변 수정 :
var stringifyError = function(err, filter, space) {
var plainObject = {};
Object.getOwnPropertyNames(err).forEach(function(key) {
plainObject[key] = err[key];
});
return JSON.stringify(plainObject, filter, space);
};
var error = new Error('testing');
error.detail = 'foo bar';
console.log(stringifyError(error, null, '\t'));
답변
이를위한 훌륭한 Node.js 패키지가 있습니다 : serialize-error
.
내 프로젝트에서 실제로 필요한 중첩 된 Error 객체도 잘 처리합니다.
답변
열거 불가능한 속성을 열거 가능하도록 재정의 할 수도 있습니다.
Object.defineProperty(Error.prototype, 'message', {
configurable: true,
enumerable: true
});
그리고 아마도 stack
재산.
답변
계층의 루트 또는 중첩 속성이 오류 인스턴스 일 수있는 임의의 개체 계층을 직렬화해야했습니다.
우리의 솔루션은 다음과 같은 replacer
매개 변수 를 사용하는 것 입니다 JSON.stringify()
.
function jsonFriendlyErrorReplacer(key, value) {
if (value instanceof Error) {
return {
// Pull all enumerable properties, supporting properties on custom Errors
...value,
// Explicitly pull Error's non-enumerable properties
name: value.name,
message: value.message,
stack: value.stack,
}
}
return value
}
let obj = {
error: new Error('nested error message')
}
console.log('Result WITHOUT custom replacer:', JSON.stringify(obj))
console.log('Result WITH custom replacer:', JSON.stringify(obj, jsonFriendlyErrorReplacer))