私は以下を持っています...
chrome.extension.sendRequest({
req: "getDocument",
docu: pagedoc,
name: 'name'
}, function(response){
var efjs = response.reply;
});
これは以下を呼び出します..
case "getBrowserForDocumentAttribute":
alert("ZOMG HERE");
sendResponse({
reply: getBrowserForDocumentAttribute(request.docu,request.name)
});
break;
しかし、私のコードが「ZOMG HERE」に達することはなく、chrome.extension.sendRequest
を実行している間に次のエラーをスローします。
Uncaught TypeError: Converting circular structure to JSON
chromeHidden.JSON.stringify
chrome.Port.postMessage
chrome.initExtension.chrome.extension.sendRequest
suggestQuery
何がこれを引き起こしているのか、誰かに何か考えがありますか?
それはあなたがリクエストで渡すオブジェクト(私はそれがpagedoc
であると思う)が循環参照を持っていることを意味します、何か:
var a = {};
a.b = a;
JSON.stringify
はこのような構造を変換することはできません。
N.B. :これは、DOMツリーにアタッチされていなくても、循環参照を持つDOMノードの場合に当てはまります。各ノードは、ほとんどの場合ownerDocument
を参照するdocument
を持ちます。 document
は少なくともdocument.body
を通じてDOMツリーへの参照を持ち、document.body.ownerDocument
は再びdocument
を参照します。これはDOMツリー内の複数の循環参照のうち、 one のみです。
MozillaのJSONドキュメント によると、JSON.Stringify
には、ツリーを解析している間に子項目をフィルタリング/無視するために使用できる2番目のパラメータcensor
があります。しかし、おそらくあなたは循環参照を避けることができます。
Node.jsではできません。だから我々はこのようなことをすることができます:
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)));
結果:
Censoring: { foo: { bar: [Circular] } }
Result: {"foo":{"bar":"[Circular]"}}
残念ながら、自動的に循環と見なされるまでに最大30回の反復があるようです。そうでなければ、これでうまくいくはずです。 areEquivalent
ここから を使ったことさえありますが、JSON.Stringify
は30回繰り返した後も例外を投げます。それでも、本当に必要な場合は、トップレベルでオブジェクトの適切な表現を取得するのに十分です。おそらく誰かがこれを改善することができますか? HTTPリクエストオブジェクトのNode.jsでは、次のようになります。
{
"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]"
}
私はここでこれを行うために小さなNode.jsモジュールを作成しました: https://github.com/ericmuyser/stringy 改善してください/貢献してください!
1つの方法は、メインオブジェクトからオブジェクトと機能を削除することです。そしてより単純な形を文字列化する
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
};
私は通常これを解決するためにcircular-json npmパッケージを使います。
// 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":"~"}
これは関連する答えではないかもしれませんが、このリンク JavaScriptで循環参照を検出して修正する は循環依存を引き起こしている オブジェクト を検出するのに役立ちます。
私はこのようにNodeJSでこの問題を解決します:
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));
以下のメッセージをjQueryで作成しようとしたときに同じエラーが発生しました。循環参照は、reviewerName
が誤ってmsg.detail.reviewerName
に割り当てられていたときに発生します。 JQueryの.val()が問題を解決しました。最後の行を見てください。
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
Zainengineerの答えに基づくと...もう1つの方法は、オブジェクトの詳細コピーを作成し、循環参照を削除して結果を文字列化することです。
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));
私はjQueryのformvaliadatorと同じエラーを得ていたが、私は成功:関数内のconsole.logを削除したとき、それはうまくいった。