是否可以使用JSON.stringify引用错误? [英] Is it not possible to stringify an Error using JSON.stringify?

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

问题描述

重现问题



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

  // node v0.10.15 
> var error = new Error('simple error message');
undefined

>错误
[错误:简单错误消息]

> Object.getOwnPropertyNames(误差);
['stack','arguments','type','message']

> JSON.stringify(误差);
'{}'

问题是我最终得到一个空对象。 / p>

我尝试了



浏览器



我第一次尝试离开node.js并在各种浏览器中运行它。 Chrome版本28给了我相同的结果,有趣的是,Firefox至少尝试了一下,但是留下了消息:

 >>> JSON.stringify(误差); // Firebug,Firefox 23 
{fileName:debug eval code,lineNumber:1,stack:@ debug eval code:1\\\
}

替换功能



然后我看了 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 ?如果没有,为什么会发生这种情况?



绕过这个

的方法


  • 粘贴简单的基于字符串的错误消息,或创建个人错误对象,不要依赖本机的Error对象。

  • 拉属性: JSON.stringify {message:error.message,stack:error.stack})



更新



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

  var error = new Error('simple error信息'); 
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,
可配置:true
参数{value:undefined,
可写:true,
可枚举:false,
可配置:true}
type {value:undefined,
可写:
可枚举:
可配置:true}
message {value:'simple error message',
可写:true,
枚举:false,
可配置:true}

密钥:枚举:false



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

解决方案

您可以定义一个 Error.prototype.toJSON 来检索代表<$ c $的 Object c>错误:

  if(!(Error.prototype中的'toJSON')
Object.defineProperty(Error.prototype,的toJSON,{
值为:函数(){
变种ALT = {};

Object.getOwnPropertyNames(this).forEach(function(key){
alt [key] = this [key];
},this);

返回alt;
},
可配置:true,
可写:true
});





  var error = new错误( '试验'); 
error.detail ='foo bar';

console.log(JSON.stringify(error));
// {message:testing,detail:foo bar}

使用 对象.defineProperty() 将$ code>添加到JSON ,而不是它是一个枚举属性本身






关于修改 Error.prototype ,而 toJSON()可能不会被定义为错误具体来说,对于一般的对象,方法仍然是标准化的(参考:步骤3)。因此,碰撞或冲突的风险很小。



尽管如此,为了完全避免这种情况, JSON.stringify()可以使用参数

  function replaceErrors(key,value){
if(value instanceof Error){
var error = {};

Object.getOwnPropertyNames(value).forEach(function(key){
error [key] = value [key];
});

返回错误;
}

返回值;
}

var error = new Error('testing');
error.detail ='foo bar';

console.log(JSON.stringify(error,replaceErrors));


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

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

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