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 Error
s 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:
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
Console.Log() Shows the Changed Value of a Variable Before the Value Actually Changes
How to Get Element by Class in JavaScript
Sleep in JavaScript - Delay Between Actions
JavaScript - Track Mouse Position
How to Chain and Share Prior Results With Promises
Prevent Address-Bar Hiding in Mobile Browsers
How to Dynamically Modify <Select> in Materialize CSS Framework
Module.Exports VS Exports in Node.Js
Difference Between Domcontentloaded and Load Events
Babel 6 Regeneratorruntime Is Not Defined
Chrome: Timeouts/Interval Suspended in Background Tabs
"Syntaxerror: Unexpected Token ≪ in Json At Position 0"
JavaScript Function to Add X Months to a Date
Tainted Canvases May Not Be Exported
Is There a Case Insensitive Jquery :Contains Selector