首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >是不是不能用JSON.stringify把一个错误串起来?

是不是不能用JSON.stringify把一个错误串起来?
EN

Stack Overflow用户
提问于 2013-08-23 05:34:01
回答 13查看 141.1K关注 0票数 436

重现问题

在尝试使用web套接字传递错误消息时,我遇到了一个问题。我可以使用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。它表明原型包含诸如toStringtoSource之类的方法。知道函数不能被字符串化,我在调用JSON.stringify来删除所有函数时包含了一个replacer function,但后来意识到它也有一些奇怪的行为:

var error = new Error('simple error message');
JSON.stringify(error, function(key, value) {
    console.log(key === ''); // true (?)
    console.log(value === error); // true (?)
});

它似乎不会像往常一样循环遍历对象,因此我不能检查键是否是函数并忽略它。

问题是

有没有办法用JSON.stringify把本机错误消息串起来?如果不是,为什么会发生这种行为?

绕过这个问题的方法

  • 坚持使用简单的基于字符串的错误消息,或者创建个人错误对象而不依赖于本机错误对象。
  • Pull属性:

更新

@Ray Toal在评论中建议我看看property descriptors。现在很清楚为什么它不起作用了:

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

Accepted提供了解决此问题的方法。

EN

回答 13

Stack Overflow用户

回答已采纳

发布于 2013-08-23 05:48:09

您可以定义Error.prototype.toJSON来检索表示Error的普通Object

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,虽然可能没有专门为Error定义toJSON(),但通常为对象定义the method is still standardized (参见:步骤3)。因此,冲突或冲突的风险是最小的。

不过,为了完全避免这种情况,可以使用JSON.stringify()'s replacer parameter

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));
票数 221
EN

Stack Overflow用户

发布于 2014-10-05 12:57:05

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

似乎很管用

[from a comment by /u/ub3rgeek on /r/javascript]和felixfbecker的评论如下

票数 361
EN

Stack Overflow用户

发布于 2018-06-07 17:50:33

由于没有人谈论为什么部分,我将回答它。

为什么此 JSON.stringify 返回空对象?

> JSON.stringify(error);
'{}'

应答

JSON.stringify()的文档中,

对于所有其他对象实例(包括Map、Set、WeakMap和WeakSet),只有它们的可枚举属性将被序列化。

而且Error对象没有它的可枚举属性,这就是为什么它打印一个空对象。

票数 152
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18391212

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档