Is it not possible to stringify an Error using JSON.stringify?(是否无法使用 JSON.stringify 对错误进行字符串化?)
问题描述
Reproducing the problem
I'm running into an issue when trying to pass error messages around using web sockets. I can replicate the issue I am facing using JSON.stringify to cater to a wider audience:
// 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);
'{}'
The problem is that I end up with an empty object.
What I've tried
Browsers
I first tried leaving node.js and running it in various browsers. Chrome version 28 gives me the same result, and interestingly enough, Firefox at least makes an attempt but left out the message:
>>> JSON.stringify(error); // Firebug, Firefox 23
{"fileName":"debug eval code","lineNumber":1,"stack":"@debug eval code:1
"}
Replacer function
I then looked at the Error.prototype. It shows that the prototype contains methods such as toString and toSource. Knowing that functions can't be stringified, I included a replacer function when calling JSON.stringify to remove all functions, but then realized that it too had some weird behavior:
var error = new Error('simple error message');
JSON.stringify(error, function(key, value) {
console.log(key === ''); // true (?)
console.log(value === error); // true (?)
});
It doesn't seem to loop over the object as it normally would, and therefore I can't check if the key is a function and ignore it.
The Question
Is there any way to stringify native Error messages with JSON.stringify? If not, why does this behavior occur?
Methods of getting around this
- Stick with simple string-based error messages, or create personal error objects and don't rely on the native Error object.
- Pull properties:
JSON.stringify({ message: error.message, stack: error.stack })
Updates
@Ray Toal Suggested in a comment that I take a look at the property descriptors. It is clear now why it does not work:
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);
}
Output:
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 }
Key: enumerable: false.
Accepted answer provides a workaround for this problem.
You can define a Error.prototype.toJSON to retrieve a plain Object representing the 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"}
Using Object.defineProperty() adds toJSON without it being an enumerable property itself.
Regarding modifying Error.prototype, while toJSON() may not be defined for Errors specifically, the method is still standardized for objects in general (ref: step 3). So, the risk of collisions or conflicts is minimal.
Though, to still avoid it completely, JSON.stringify()'s replacer parameter can be used instead:
function replaceErrors(key, value) {
if (value instanceof Error) {
var error = {};
Object.getOwnPropertyNames(value).forEach(function (propName) {
error[propName] = value[propName];
});
return error;
}
return value;
}
var error = new Error('testing');
error.detail = 'foo bar';
console.log(JSON.stringify(error, replaceErrors));
这篇关于是否无法使用 JSON.stringify 对错误进行字符串化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:是否无法使用 JSON.stringify 对错误进行字符串化?
基础教程推荐
- Bokeh Div文本对齐 2022-01-01
- 检查 HTML5 拖放文件类型 2022-01-01
- 原生拖动事件后如何获取 mouseup 事件? 2022-01-01
- Fabric JS绘制具有活动形状的多边形 2022-01-01
- Bootstrap 模态出现在背景下 2022-01-01
- 在 contenteditable 中精确拖放 2022-01-01
- npm start 错误与 create-react-app 2022-01-01
- fetch 是否支持原生多文件上传? 2022-01-01
- 如何添加到目前为止的天数? 2022-01-01
- 即使用户允许,Gmail 也会隐藏外部电子邮件图片 2022-01-01
