Jay*_*com 289 javascript error-handling json node.js
尝试使用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);
'{}'
Run Code Online (Sandbox Code Playgroud)
问题是我最终得到一个空对象.
浏览器
我首先尝试离开node.js并在各种浏览器中运行它.Chrome版本28给了我相同的结果,有趣的是,Firefox至少做了一次尝试,但遗漏了消息:
>>> JSON.stringify(error); // Firebug, Firefox 23
{"fileName":"debug eval code","lineNumber":1,"stack":"@debug eval code:1\n"}
Run Code Online (Sandbox Code Playgroud)
替换功能
然后我查看了Error.prototype.它表明原型包含诸如toString和toSource之类的方法.知道函数不能被字符串化,我在调用JSON.stringify时包含了一个replacer函数来删除所有函数,但后来意识到它也有一些奇怪的行为:
var error = new Error('simple error message');
JSON.stringify(error, function(key, value) {
console.log(key === ''); // true (?)
console.log(value === error); // true (?)
});
Run Code Online (Sandbox Code Playgroud)
它似乎不像通常那样循环遍历对象,因此我无法检查密钥是否是函数并忽略它.
有没有办法用字符串化本机错误消息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);
}
Run Code Online (Sandbox Code Playgroud)
输出:
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 }
Run Code Online (Sandbox Code Playgroud)
关键:enumerable: false
.
已接受的答案提供了此问题的解决方法.
lag*_*lex 214
JSON.stringify(err, Object.getOwnPropertyNames(err))
Run Code Online (Sandbox Code Playgroud)
似乎工作
[ 来自/ u/ub3rgeek对/ r/javascript的评论]和felixfbecker的评论如下
Jon*_*ski 156
您可以定义一个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
});
Run Code Online (Sandbox Code Playgroud)
var error = new Error('testing');
error.detail = 'foo bar';
console.log(JSON.stringify(error));
// {"message":"testing","detail":"foo bar"}
Run Code Online (Sandbox Code Playgroud)
使用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));
Run Code Online (Sandbox Code Playgroud)
Bry*_*sen 45
修改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'));
Run Code Online (Sandbox Code Playgroud)
San*_*Lee 42
由于没有人在谈论原因,我会回答这些问题
问:有没有办法用JSON.stringify对本机错误消息进行字符串化?
没有.
问:如果没有,为什么会出现这种情况?
从JSON.stringify()的文档,
对于所有其他Object实例(包括Map,Set,WeakMap和WeakSet),只会序列化它们的可枚举属性.
和JSON.stringify
object没有它的可枚举属性,这就是它打印一个空对象的原因.
Luk*_*ski 15
有一个伟大的Node.js包: serialize-error
.
它甚至可以处理嵌套的Error对象,我在项目中实际需要的东西.
https://www.npmjs.com/package/serialize-error
Joe*_*one 10
我们需要序列化任意对象层次结构,其中根或层次结构中的任何嵌套属性都可以是 Error 的实例。
我们的解决方案是使用 的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))
Run Code Online (Sandbox Code Playgroud)
Jas*_*son 10
我正在研究日志附加程序的 JSON 格式,并最终在这里尝试解决类似的问题。过了一会儿,我意识到我可以让 Node 来完成这项工作:
const util = require("util");
...
return JSON.stringify(obj, (name, value) => {
if (value instanceof Error) {
return util.format(value);
} else {
return value;
}
}
Run Code Online (Sandbox Code Playgroud)
Dav*_*kal 10
如果使用nodejs,则使用本机nodejs有更好可靠的方法inspect
。您还可以指定将对象打印到无限深度。
打字稿示例:
import { inspect } from "util";
const myObject = new Error("This is error");
console.log(JSON.stringify(myObject)); // Will print {}
console.log(myObject); // Will print full error object
console.log(inspect(myObject, {depth: null})); // Same output as console.log plus it works as well for objects with many nested properties.
Run Code Online (Sandbox Code Playgroud)
并且在堆栈溢出的主题中也进行了How can I get the full object in Node.js's console.log(), rather than '[Object]'?
讨论。
小智 8
您还可以将这些不可枚举的属性重新定义为可枚举.
Object.defineProperty(Error.prototype, 'message', {
configurable: true,
enumerable: true
});
Run Code Online (Sandbox Code Playgroud)
也许stack
属性也是.
字符串构造函数应该能够字符串化错误
try {
throw new Error("MY ERROR MSG")
} catch (e) {
String(e) // returns 'Error: MY ERROR MSG'
}
Run Code Online (Sandbox Code Playgroud)
小智 6
上面的答案似乎都没有正确序列化 Error 原型上的属性(因为getOwnPropertyNames()
不包括继承的属性)。我也无法像建议的答案之一那样重新定义属性。
这是我提出的解决方案 - 它使用 lodash,但您可以用这些函数的通用版本替换 lodash。
function recursivePropertyFinder(obj){
if( obj === Object.prototype){
return {};
}else{
return _.reduce(Object.getOwnPropertyNames(obj),
function copy(result, value, key) {
if( !_.isFunction(obj[value])){
if( _.isObject(obj[value])){
result[value] = recursivePropertyFinder(obj[value]);
}else{
result[value] = obj[value];
}
}
return result;
}, recursivePropertyFinder(Object.getPrototypeOf(obj)));
}
}
Error.prototype.toJSON = function(){
return recursivePropertyFinder(this);
}
Run Code Online (Sandbox Code Playgroud)
这是我在 Chrome 中进行的测试:
var myError = Error('hello');
myError.causedBy = Error('error2');
myError.causedBy.causedBy = Error('error3');
myError.causedBy.causedBy.displayed = true;
JSON.stringify(myError);
{"name":"Error","message":"hello","stack":"Error: hello\n at <anonymous>:66:15","causedBy":{"name":"Error","message":"error2","stack":"Error: error2\n at <anonymous>:67:20","causedBy":{"name":"Error","message":"error3","stack":"Error: error3\n at <anonymous>:68:29","displayed":true}}}
Run Code Online (Sandbox Code Playgroud)
只需转换为常规对象即可
// example error
let err = new Error('I errored')
// one liner converting Error into regular object that can be stringified
err = Object.getOwnPropertyNames(err).reduce((acc, key) => { acc[key] = err[key]; return acc; }, {})
Run Code Online (Sandbox Code Playgroud)
如果您想从子进程、工作进程或通过网络发送此对象,则无需字符串化。它将像任何其他普通对象一样自动字符串化和解析
归档时间: |
|
查看次数: |
77143 次 |
最近记录: |