Is It Not Possible to Stringify an Error Using Json.Stringify

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

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 (propName) {
error[propName] = value[propName];
});

return error;
}

return value;
}

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

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

Why does JSON.stringify on TypeError return an empty object

When you use stringify on a TypeError, you're stringifying an object with no enumerable properties.

So if you do

var typeError = new TypeError("hey")
for(var prop in typeError) {
console.log(prop) // this does not run
}

When you log using console.log, you're using valueOf, so

var typeError = new TypeError("hey")
typeError.valueOf() // TypeError: hey(…)

Also, an error knows how to turn itself into a string, so this works too:

var typeError = new TypeError("hey")
typeError.toString() // "TypeError: hey"

If you want to log the properties of an object you can't see using a normal log, you can console.dir the object.

When you do it on the typeError, you'll see that it has a message property:

Sample Image

Why JSON.stringify() don't work correctly

You are attempting to use a 'sparse array' to store your data. Arrays do not have a clear way to be instantiated with elements at a specified index.

An object (or a Map) would suit your requirements better. To use an object, I modified your 'accounts' initation code that was commented:

// replace this:
dataObj["accounts"] = [];
// with this:
dataObj["accounts"] = {};

The other code you are using (e.g. accessing elements using the square brackets) will work the same. You should probably make the same adjustments to the other arrays you are using.

Sparse arrays can get ugly in some notations if you have large blank spaces (which your UUID methodology would certainly have). An object or a Map will not suffer that shortcoming.

An example of similar code, using objects instead of arrays:

let dataObj = {};
dataObj["accounts"] = {};
let uuid = 'abcdefghij12344';
dataObj["accounts"][uuid] = {}
dataObj["accounts"][uuid]['active'] = true;
dataObj["accounts"][uuid]['someotherval'] = true;

console.log(dataObj);
//outputs:

{ accounts: { abcdefghij12344: { active: true, someotherval: true } } }

let stringified = JSON.stringify(dataObj);
console.log(stringified);

// Outputs:
{"accounts":{"abcdefghij12344":{"active":true,"someotherval":true}}}

let parsed = JSON.parse(stringified);
console.log(parsed);

//Outputs:
{ accounts: { abcdefghij12344: { active: true, someotherval: true } } }

Problem when using JSON.stringify in NodeJS

It's an array not an object. If randomJsonObject was an object then this would have worked.

Try the following, set randomJsonObect = {} in the beginning and do your experiment again.

nodejs - JSON.stringify Error object

The issue has to do with the fact that some of the properties set on Errors are configured as non-enumerable.

Here's something you can use to properly stringify Error objects, it sets a toJSON() method that JSON.stringify() looks for when converting an object:

var config = {
configurable: true,
value: function() {
var alt = {};
var storeKey = function(key) {
alt[key] = this[key];
};
Object.getOwnPropertyNames(this).forEach(storeKey, this);
return alt;
}
};
Object.defineProperty(Error.prototype, 'toJSON', config);

Then just use JSON.stringify() as normal.

Why does an infinite recursion error appear while processing JSON.stringify

The object most likely contains cycles, where an object in the tree references another object, which eventually references that first object. I find this issue occurs a lot with errors like those from axios because the response object refers to a request object, and the request object has a reference to the response object.

It's an irritating problem that often bites us. Thankfully, there are libraries like json-decycle and others to solve this problem by changing circular references to something that can be serialized without a stack overflow.



Related Topics



Leave a reply



Submit