wake-up-neo.com

Chrome sendrequest error: TypeError: Konvertieren der Kreisstruktur in JSON

Ich habe folgendes ...

chrome.extension.sendRequest({
  req: "getDocument",
  docu: pagedoc,
  name: 'name'
}, function(response){
  var efjs = response.reply;
});

das nennt das folgende ..

case "getBrowserForDocumentAttribute":
  alert("ZOMG HERE");
  sendResponse({
    reply: getBrowserForDocumentAttribute(request.docu,request.name)
  });
  break;

Mein Code erreicht jedoch nie "ZOMG HERE", sondern löst den folgenden Fehler aus, während chrome.extension.sendRequest ausgeführt wird.

 Uncaught TypeError: Converting circular structure to JSON
 chromeHidden.JSON.stringify
 chrome.Port.postMessage
 chrome.initExtension.chrome.extension.sendRequest
 suggestQuery

Hat jemand eine Ahnung, was das verursacht?

351
Skizit

Dies bedeutet, dass das Objekt, das Sie in der Anfrage übergeben haben (ich vermute, es ist pagedoc), einen Zirkelverweis hat, etwa:

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

JSON.stringify kann solche Strukturen nicht konvertieren.

N.B.: Dies ist bei DOM-Knoten der Fall, die kreisförmige Verweise haben, auch wenn sie nicht an den DOM-Baum angehängt sind. Jeder Knoten hat ein ownerDocument, das sich in den meisten Fällen auf document bezieht. document hat einen Verweis auf den DOM-Baum, zumindest durch document.body und document.body.ownerDocument verweist wieder auf document, was nur eins ist von mehreren Zirkelverweisen in der DOM-Struktur.

463
Felix Kling

Gemäß den JSON-Dokumenten bei Mozilla hat JSON.Stringify einen zweiten Parameter censor, mit dem untergeordnete Elemente beim Parsen des Baums gefiltert/ignoriert werden können. Vielleicht können Sie jedoch die Zirkelverweise umgehen.

In Node.js können wir nicht. Also können wir so etwas machen:

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

Das Ergebnis:

Censoring:  { foo: { bar: [Circular] } }
Result: {"foo":{"bar":"[Circular]"}}

Leider scheint es maximal 30 Iterationen zu geben, bevor es automatisch annimmt, dass es zirkulär ist. Ansonsten sollte dies funktionieren. Ich habe sogar areEquivalentvon hier verwendet, aber JSON.Stringify löst nach 30 Iterationen immer noch die Ausnahme aus. Trotzdem ist es gut genug, um eine anständige Darstellung des Objekts auf höchster Ebene zu erhalten, wenn Sie es wirklich brauchen. Vielleicht kann das jemand verbessern? In Node.js für ein HTTP-Anforderungsobjekt erhalte ich:

{
"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]"
}

Ich habe ein kleines Node.js-Modul erstellt, um dies hier zu tun: https://github.com/ericmuyser/stringy Fühlen Sie sich frei, zu verbessern/beizutragen!

117
Eric Muyser

Ein Ansatz ist das Entfernen von Objekten und Funktionen vom Hauptobjekt. Und stringifiziere die einfachere Form

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
};
35
zainengineer

Normalerweise benutze ich das Circular-Json Npm-Paket, um dieses Problem zu lösen.

// 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

20
user3139574

Dies könnte keine verwandte Antwort sein, aber dieser Link Erkennen und Korrigieren von Zirkelverweisen in JavaScript könnte hilfreich sein, um verursachende Objekte zu erkennen zirkuläre Abhängigkeit.

5

Ich löse dieses Problem auf NodeJS wie folgt:

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

Basierend auf der Antwort von zainengineer ... Ein anderer Ansatz besteht darin, eine tiefe Kopie des Objekts anzufertigen, kreisförmige Referenzen zu entfernen und das Ergebnis zu stringifizieren.

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));
4
C.M.

Beim Versuch, die folgende Nachricht mit jQuery zu erstellen, ist derselbe Fehler aufgetreten. Der Zirkelverweis tritt auf, wenn reviewerName fälschlicherweise msg.detail.reviewerName zugewiesen wurde. JQueries .val () hat das Problem behoben, siehe letzte Zeile.

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
2
izilotti

Ich habe den gleichen Fehler mit jQuery formvaliadator erhalten, aber als ich eine console.log innerhalb von success: function entfernt habe, hat es funktioniert.

0
Azmeer