Is it not possible to stringify an Error using JSON.stringify?

后端 未结 11 2080
心在旅途
心在旅途 2020-11-22 07:54

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 J

相关标签:
11条回答
  • 2020-11-22 08:36

    I was working on a JSON format for log appenders and ended up here trying to solve a similar problem. After a while, I realized I could just make Node do the work:

    const util = require("util");
    ...
    return JSON.stringify(obj, (name, value) => {
        if (value instanceof Error) {
            return util.format(value);
        } else {
            return value;
        }
    }
    
    0 讨论(0)
  • 2020-11-22 08:37

    You can solve this with a one-liner( errStringified ) in plain javascript:

    var error = new Error('simple error message');
    var errStringified = (err => JSON.stringify(Object.getOwnPropertyNames(Object.getPrototypeOf(err)).reduce(function(accumulator, currentValue) { return accumulator[currentValue] = err[currentValue], accumulator}, {})))(error);
    console.log(errStringified);
    

    It works with DOMExceptions as well.

    0 讨论(0)
  • 2020-11-22 08:44

    There is a great Node.js package for that: serialize-error.

    npm install serialize-error
    

    It handles well even nested Error objects.

    import {serializeError} from 'serialize-error';
    
    JSON.stringify(serializeError(error));
    

    Docs: https://www.npmjs.com/package/serialize-error

    0 讨论(0)
  • 2020-11-22 08:47

    None of the answers above seemed to properly serialize properties which are on the prototype of Error (because getOwnPropertyNames() does not include inherited properties). I was also not able to redefine the properties like one of the answers suggested.

    This is the solution I came up with - it uses lodash but you could replace lodash with generic versions of those functions.

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

    Here's the test I did in 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}}}  
    
    0 讨论(0)
  • 2020-11-22 08:48

    Make it serializable

    // 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; }, {})
    

    If you want to send this object from child process, worker or though the network there's no need to stringify. It will be automatically stringified and parsed like any other normal object

    0 讨论(0)
提交回复
热议问题