문제 재현
웹 소켓 사용과 관련된 오류 메시지를 전달하려고 할 때 문제가 발생했습니다. 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))
