J'ai le suivant ...
chrome.extension.sendRequest({
req: "getDocument",
docu: pagedoc,
name: 'name'
}, function(response){
var efjs = response.reply;
});
qui appelle ce qui suit ..
case "getBrowserForDocumentAttribute":
alert("ZOMG HERE");
sendResponse({
reply: getBrowserForDocumentAttribute(request.docu,request.name)
});
break;
Cependant, mon code n'atteint jamais "ZOMG HERE", mais renvoie l'erreur suivante lors de l'exécution de chrome.extension.sendRequest
Uncaught TypeError: Converting circular structure to JSON
chromeHidden.JSON.stringify
chrome.Port.postMessage
chrome.initExtension.chrome.extension.sendRequest
suggestQuery
Est-ce que quelqu'un a une idée de ce qui cause cela?
Cela signifie que l'objet que vous transmettez dans la demande (je suppose que c'est pagedoc
) a une référence circulaire, quelque chose comme:
var a = {};
a.b = a;
JSON.stringify
ne peut pas convertir de telles structures.
N.B.: Ce serait le cas des nœuds DOM, qui ont des références circulaires, même s'ils ne sont pas attachés à l'arborescence DOM. Chaque nœud a un ownerDocument
qui fait référence à document
dans la plupart des cas. document
a une référence à l’arbre DOM au moins par le biais de document.body
et document.body.ownerDocument
renvoie à document
, ce qui n’est que un de multiples références circulaires dans l’arbre DOM.
Conformément à les documents JSON sur Mozilla , JSON.Stringify
possède un deuxième paramètre censor
qui peut être utilisé pour filtrer/ignorer les éléments enfants lors de l'analyse de l'arborescence. Cependant, vous pouvez peut-être éviter les références circulaires.
Dans Node.js, nous ne pouvons pas. Donc, nous pouvons faire quelque chose comme ça:
function censor(censor) {
var i = 0;
return function(key, value) {
if(i !== 0 && typeof(censor) === 'object' && typeof(value) == 'object' && censor == value)
return '[Circular]';
if(i >= 29) // seems to be a harded maximum of 30 serialized objects?
return '[Unknown]';
++i; // so we know we aren't using the original object anymore
return value;
}
}
var b = {foo: {bar: null}};
b.foo.bar = b;
console.log("Censoring: ", b);
console.log("Result: ", JSON.stringify(b, censor(b)));
Le résultat:
Censoring: { foo: { bar: [Circular] } }
Result: {"foo":{"bar":"[Circular]"}}
Malheureusement, il semble y avoir un maximum de 30 itérations avant de supposer automatiquement qu'il est circulaire. Sinon, cela devrait fonctionner. J'ai même utilisé areEquivalent
à partir d'ici , mais JSON.Stringify
lève toujours l'exception après 30 itérations. Néanmoins, il est suffisant d'obtenir une représentation décente de l'objet au plus haut niveau, si vous en avez vraiment besoin. Peut-être que quelqu'un peut améliorer cela cependant? Dans Node.js pour un objet de requête HTTP, j'obtiens:
{
"limit": null,
"size": 0,
"chunks": [],
"writable": true,
"readable": false,
"_events": {
"pipe": [null, null],
"error": [null]
},
"before": [null],
"after": [],
"response": {
"output": [],
"outputEncodings": [],
"writable": true,
"_last": false,
"chunkedEncoding": false,
"shouldKeepAlive": true,
"useChunkedEncodingByDefault": true,
"_hasBody": true,
"_trailer": "",
"finished": false,
"socket": {
"_handle": {
"writeQueueSize": 0,
"socket": "[Unknown]",
"onread": "[Unknown]"
},
"_pendingWriteReqs": "[Unknown]",
"_flags": "[Unknown]",
"_connectQueueSize": "[Unknown]",
"destroyed": "[Unknown]",
"bytesRead": "[Unknown]",
"bytesWritten": "[Unknown]",
"allowHalfOpen": "[Unknown]",
"writable": "[Unknown]",
"readable": "[Unknown]",
"server": "[Unknown]",
"ondrain": "[Unknown]",
"_idleTimeout": "[Unknown]",
"_idleNext": "[Unknown]",
"_idlePrev": "[Unknown]",
"_idleStart": "[Unknown]",
"_events": "[Unknown]",
"ondata": "[Unknown]",
"onend": "[Unknown]",
"_httpMessage": "[Unknown]"
},
"connection": "[Unknown]",
"_events": "[Unknown]",
"_headers": "[Unknown]",
"_headerNames": "[Unknown]",
"_pipeCount": "[Unknown]"
},
"headers": "[Unknown]",
"target": "[Unknown]",
"_pipeCount": "[Unknown]",
"method": "[Unknown]",
"url": "[Unknown]",
"query": "[Unknown]",
"ended": "[Unknown]"
}
J'ai créé un petit module Node.js pour le faire ici: https://github.com/ericmuyser/stringy N'hésitez pas à améliorer/contribuer!
Une approche consiste à supprimer l'objet et les fonctions de l'objet principal. Et stringifier la forme plus simple
function simpleStringify (object){
var simpleObject = {};
for (var prop in object ){
if (!object.hasOwnProperty(prop)){
continue;
}
if (typeof(object[prop]) == 'object'){
continue;
}
if (typeof(object[prop]) == 'function'){
continue;
}
simpleObject[prop] = object[prop];
}
return JSON.stringify(simpleObject); // returns cleaned up JSON
};
J'utilise normalement le paquet circular-json npm pour résoudre ce problème.
// Felix Kling's example
var a = {};
a.b = a;
// load circular-json module
var CircularJSON = require('circular-json');
console.log(CircularJSON.stringify(a));
//result
{"b":"~"}
Cela pourrait ne pas être une réponse liée, mais ce lien Détecter et corriger les références circulaires en JavaScript pourrait être utile pour détecter les objets qui causent dépendance circulaire.
Je résous ce problème sur NodeJS comme ceci:
var util = require('util');
// Our circular object
var obj = {foo: {bar: null}, a:{a:{a:{a:{a:{a:{a:{hi: 'Yo!'}}}}}}}};
obj.foo.bar = obj;
// Generate almost valid JS object definition code (typeof string)
var str = util.inspect(b, {depth: null});
// Fix code to the valid state (in this example it is not required, but my object was huge and complex, and I needed this for my case)
str = str
.replace(/<Buffer[ \w\.]+>/ig, '"buffer"')
.replace(/\[Function]/ig, 'function(){}')
.replace(/\[Circular]/ig, '"Circular"')
.replace(/\{ \[Function: ([\w]+)]/ig, '{ $1: function $1 () {},')
.replace(/\[Function: ([\w]+)]/ig, 'function $1(){}')
.replace(/(\w+): ([\w :]+GMT\+[\w \(\)]+),/ig, '$1: new Date("$2"),')
.replace(/(\S+): ,/ig, '$1: null,');
// Create function to eval stringifyed code
var foo = new Function('return ' + str + ';');
// And have fun
console.log(JSON.stringify(foo(), null, 4));
Basé sur la réponse de zainengineer ... Une autre approche consiste à créer une copie complète de l'objet et à supprimer les références circulaires afin de renforcer le résultat.
function cleanStringify(object) {
if (object && typeof object === 'object') {
object = copyWithoutCircularReferences([object], object);
}
return JSON.stringify(object);
function copyWithoutCircularReferences(references, object) {
var cleanObject = {};
Object.keys(object).forEach(function(key) {
var value = object[key];
if (value && typeof value === 'object') {
if (references.indexOf(value) < 0) {
references.Push(value);
cleanObject[key] = copyWithoutCircularReferences(references, value);
references.pop();
} else {
cleanObject[key] = '###_Circular_###';
}
} else if (typeof value !== 'function') {
cleanObject[key] = value;
}
});
return cleanObject;
}
}
// Example
var a = {
name: "a"
};
var b = {
name: "b"
};
b.a = a;
a.b = b;
console.log(cleanStringify(a));
console.log(cleanStringify(b));
J'ai rencontré la même erreur en essayant de construire le message ci-dessous avec jQuery. La référence circulaire se produit lorsque reviewerName
a été affecté par erreur à msg.detail.reviewerName
. .Val () de JQuery a corrigé le problème, voir dernière ligne.
var reviewerName = $('reviewerName'); // <input type="text" id="taskName" />;
var msg = {"type":"A", "detail":{"managerReview":true} };
msg.detail.reviewerName = reviewerName; // Error
msg.detail.reviewerName = reviewerName.val(); // Fixed
La même erreur se produisait avec jQuery formvaliadator, mais lorsque j'ai supprimé un fichier console.log inside success: function, cela fonctionnait.