60 lines
1.2 KiB
JavaScript
60 lines
1.2 KiB
JavaScript
|
var hasProp = Object.prototype.hasOwnProperty;
|
||
|
|
||
|
function throwsMessage(err) {
|
||
|
return '[Throws: ' + (err ? err.message : '?') + ']';
|
||
|
}
|
||
|
|
||
|
function safeGetValueFromPropertyOnObject(obj, property) {
|
||
|
if (hasProp.call(obj, property)) {
|
||
|
try {
|
||
|
return obj[property];
|
||
|
}
|
||
|
catch (err) {
|
||
|
return throwsMessage(err);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return obj[property];
|
||
|
}
|
||
|
|
||
|
function ensureProperties(obj) {
|
||
|
var seen = [ ]; // store references to objects we have seen before
|
||
|
|
||
|
function visit(obj) {
|
||
|
if (obj === null || typeof obj !== 'object') {
|
||
|
return obj;
|
||
|
}
|
||
|
|
||
|
if (seen.indexOf(obj) !== -1) {
|
||
|
return '[Circular]';
|
||
|
}
|
||
|
seen.push(obj);
|
||
|
|
||
|
if (typeof obj.toJSON === 'function') {
|
||
|
try {
|
||
|
return visit(obj.toJSON());
|
||
|
} catch(err) {
|
||
|
return throwsMessage(err);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Array.isArray(obj)) {
|
||
|
return obj.map(visit);
|
||
|
}
|
||
|
|
||
|
return Object.keys(obj).reduce(function(result, prop) {
|
||
|
// prevent faulty defined getter properties
|
||
|
result[prop] = visit(safeGetValueFromPropertyOnObject(obj, prop));
|
||
|
return result;
|
||
|
}, {});
|
||
|
};
|
||
|
|
||
|
return visit(obj);
|
||
|
}
|
||
|
|
||
|
module.exports = function(data) {
|
||
|
return JSON.stringify(ensureProperties(data));
|
||
|
}
|
||
|
|
||
|
module.exports.ensureProperties = ensureProperties;
|