Serialisierungsobjekt, das einen zyklischen Objektwert enthält
-
28-10-2019 - |
Frage
Ich habe ein Objekt (Analysebaum), das untergeordnete Knoten enthält, die auf andere Knoten verweisen.
Ich möchte dieses Objekt mit JSON.stringify()
serialisieren, aber ich bekomme
TypeError: zyklischer Objektwert
wegen der Konstrukte, die ich erwähnt habe.
Wie könnte ich das umgehen?Es ist mir egal, ob diese Verweise auf andere Knoten im serialisierten Objekt dargestellt werden oder nicht.
Andererseits scheint es mühsam, diese Eigenschaften beim Erstellen aus dem Objekt zu entfernen, und ich möchte keine Änderungen am Parser (Narzisse) vornehmen.
Lösung
Verwenden Sie den zweiten Parameter von stringify
, den Ersetzungsfunktion , um bereits serialisierte Objekte auszuschließen:
var seen = [];
JSON.stringify(obj, function(key, val) {
if (val != null && typeof val == "object") {
if (seen.indexOf(val) >= 0) {
return;
}
seen.push(val);
}
return val;
});
Wie in anderen Kommentaren richtig ausgeführt, entfernt dieser Code jedes "gesehene" Objekt, nicht nur "rekursive".
Zum Beispiel für:
a = {x:1};
obj = [a, a];
Das Ergebnis ist falsch. Wenn Ihre Struktur so ist, möchten Sie möglicherweise Crockfords Decycle oder diese (einfachere) Funktion, die nur rekursive Referenzen durch Nullen ersetzt:
Andere Tipps
Ich habe einen GitHub Gist erstellt, der zyklische Strukturen erkennen und auch de- und codieren kann: https://gist.github.com/Hoff97/9842228
Verwenden Sie zum Transformieren einfach JSONE.stringify / JSONE.parse. Es de- und codiert auch Funktionen.Wenn Sie dies deaktivieren möchten, entfernen Sie einfach die Zeilen 32-48 und 61-85.
var strg = JSONE.stringify(cyclicObject);
var cycObject = JSONE.parse(strg);
Ein Beispiel für eine Geige finden Sie hier:
viel sparen und es zeigt, wo sich ein Zyklus Objekt befand.
<script>
var jsonify=function(o){
var seen=[];
var jso=JSON.stringify(o, function(k,v){
if (typeof v =='object') {
if ( !seen.indexOf(v) ) { return '__cycle__'; }
seen.push(v);
} return v;
});
return jso;
};
var obj={
g:{
d:[2,5],
j:2
},
e:10
};
obj.someloopshere = [
obj.g,
obj,
{ a: [ obj.e, obj ] }
];
console.log('jsonify=',jsonify(obj));
</script>
erzeugt
jsonify = {"g":{"d":[2,5],"j":2},"e":10,"someloopshere":[{"d":[2,5],"j":2},"__cycle__",{"a":[10,"__cycle__"]}]}
function stringifyObject ( obj ) {
if ( _.isArray( obj ) || !_.isObject( obj ) ) {
return obj.toString()
}
var seen = [];
return JSON.stringify(
obj,
function( key, val ) {
if (val != null && typeof val == "object") {
if ( seen.indexOf( val ) >= 0 )
return
seen.push( val )
}
return val
}
);
}
Eine Vorbedingung fehlte, andernfalls werden die ganzzahligen Werte in Array-Objekten abgeschnitten, d. h. [[08.11.2014 12:30:13, 1095]] 1095 wird auf 095 reduziert.
Ich erstelle auch ein Github-Projekt, das zyklische Objekte serialisieren und die Klasse wiederherstellen kann, wenn Sie sie wie ein String im Attribut serializename speichern
var d={}
var a = {b:25,c:6,enfant:d};
d.papa=a;
var b = serializeObjet(a);
assert.equal( b, "{0:{b:25,c:6,enfant:'tab[1]'},1:{papa:'tab[0]'}}" );
var retCaseDep = parseChaine(b)
assert.equal( retCaseDep.b, 25 );
assert.equal( retCaseDep.enfant.papa, retCaseDep );
https://github.com/bormat/serializeStringifyParseCyclicObject
Bearbeiten: Ich habe mein Skript für NPM https://github.com/bormat/borto_circular_serialize geändert und habe Änderungen vorgenommenFunktionsnamen von Französisch bis Englisch.