是否无法使用 JSON.stringify 将错误字符串化? [英] Is it not possible to stringify an Error using JSON.stringify?

查看:36
本文介绍了是否无法使用 JSON.stringify 将错误字符串化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在尝试使用网络套接字传递错误消息时遇到问题.我可以使用 JSON.stringify 复制我面临的问题以迎合更广泛的受众:

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.

浏览器

我首先尝试离开 node.js 并在各种浏览器中运行它.Chrome 版本 28 给了我相同的结果,有趣的是,Firefox 至少进行了尝试,但忽略了消息:

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
"}

替换功能

然后我查看了 Error.prototype.它表明原型包含诸如 toStringtoSource.知道函数不能被字符串化,我添加了一个 replacer function 当调用 JSON.stringify 删除所有函数,但随后意识到它也有一些奇怪的行为:

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.

有没有办法用 JSON.stringify 将本地错误消息字符串化?如果没有,为什么会出现这种行为?

Is there any way to stringify native Error messages with JSON.stringify? If not, why does this behavior occur?

  • 坚持使用简单的基于字符串的错误消息,或创建个人错误对象,不要依赖本机 Error 对象.
  • 拉取属性:JSON.stringify({ message: error.message, stack: error.stack })

@Ray Toal 在评论中建议我看一下 属性描述符.现在很清楚为什么它不起作用:

@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);
}

输出:

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 }

键:可枚举:false.

接受的答案提供了解决此问题的方法.

Accepted answer provides a workaround for this problem.

推荐答案

您可以定义一个 Error.prototype.toJSON 来检索代表 的普通 Object错误:

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"}

使用 Object.defineProperty() 添加 toJSON 而不是 enumerable 属性本身.

Using Object.defineProperty() adds toJSON without it being an enumerable property itself.

关于修改Error.prototype,虽然toJSON()可能没有专门为Error定义,该方法对于一般对象仍然是标准化的(参考:步骤 3).因此,发生碰撞或冲突的风险很小.

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.

不过,为了完全避免它,可以使用 JSON.stringify()replacer 参数 代替:

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 将错误字符串化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆