function stringifyCyclicJSON(sourceObject, maxDepth = 5)
{
var knownObjects = {};
var jsonString = '';
recStringifyObject(sourceObject, '', 1, 'root');
return jsonString;
function recStringifyObject(currentObject, indent, level, path)
{
var isArray = (currentObject instanceof Array);
var subIndent = indent + '\t';
var i = 0;
jsonString += (isArray ? '[' : '{');
if (isArray)
{
for (; i < currentObject.length; i++)
{
doSingleStringify(i, '');
}
}
else
{
for (var key in currentObject)
{
if (currentObject[key] !== undefined)
{
doSingleStringify(key, '"' + key + '": ');
i++;
}
}
}
jsonString += (i > 0 ? '\n' + indent : ' ') + (isArray ? ']' : '}');
function doSingleStringify(key, addBefore)
{
var value = currentObject[key];
jsonString += '\n'
+ subIndent
+ (i > 0 ? ', ' : '')
+ addBefore;
if (typeof value == 'object')
{
// first search in known Objects
var found = false;
for (var pathKey in knownObjects)
{
if (knownObjects[pathKey] == value)
{
jsonString += '"[' + pathKey + ']"';
found = true;
}
}
if (!found)
{
var newPath = path + (isArray ? '[' + key + ']' : '.' + key);
knownObjects[newPath] = value;
if (level < maxDepth)
{
recStringifyObject(value, subIndent, level + 1, newPath);
}
else
{
jsonString += '"[' + (value instanceof Array ? 'Array' : 'Object') + ']"';
}
}
}
else if (typeof value == 'function')
{
jsonString += '"[Function]"';
}
else
{
jsonString += JSON.stringify(value);
}
}
}
}
Comments