2011-01-27 36 views
298

我有以下...鉻sendRequest將錯誤:類型錯誤:轉換圓形結構,以JSON

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 

有誰而引發以下錯誤有什麼想法是什麼造成這個?

+1

您嘗試發送中有循環引用的對象。什麼是'pagedoc`? – 2011-01-27 12:10:38

+0

你是什麼意思? – Skizit 2011-01-27 12:11:13

+6

我的意思是什麼? 1.「pagedoc」的價值是什麼? 2.循環參考:`a = {}; a.b = a;` – 2011-01-27 12:13:28

回答

390

這意味着你的要求(我猜是pagedoc)傳遞對象有一個循環引用,是這樣的:

var a = {}; 
a.b = a; 

JSON.stringify這樣不能轉換結構。

N.B.:即使沒有附加到DOM樹,DOM節點也會出現這種情況,即具有循環引用的DOM節點。每個節點都有一個ownerDocument,在大多數情況下它指的是documentdocument至少通過document.bodydocument.body.ownerDocument對DOM樹的引用再次引用爲document,其僅在DOM樹中的多個循環引用的一個

2

我在嘗試使用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 
103

作爲每the JSON docs at MozillaJSON.Stringify具有可用於過濾/忽略兒童物品在解析樹中的一個第二參數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次迭代之前,它會自動假定它是圓形的。否則,這應該工作。我甚至使用了areEquivalentfrom here,但JSON.Stringify仍然在30次迭代後拋出異常。儘管如此,如果你真的需要的話,還是可以在頂層獲得一個體面的對象代表。也許有人可以改善這一點呢?在Node.js的一個HTTP請求對象,我越來越:

{ 
"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隨意提高/貢獻!

29

一種方法是從主對象中剝離對象和函數。和字符串化形式更簡單

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 
}; 
3

我解決這個問題上的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)); 
12

我通常使用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":"~"} 

https://www.npmjs.com/package/circular-json

0

我正在與jqurty formvaliadator同樣的錯誤,但是當我刪除裏面成功的console.log:函數,它的工作。

1

根據zainengineer的回答...另一種方法是製作對象的深層副本並剝離循環引用並將結果串化。

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));

相關問題