他のノードへの参照である子ノードを含むオブジェクト(解析ツリー)があります。
JSON.stringify()
を使用してこのオブジェクトをシリアライズしたいのですが、私が言った構成体のために、TypeError: cyclic object value
を取得します。
どうすればこれを回避できますか?他のノードへのこれらの参照がシリアル化されたオブジェクトで表されるかどうかは私には関係ありません。
一方、作成中のオブジェクトからこれらのプロパティを削除するのは退屈なようで、パーサー(水仙)に変更を加えたくありません。
stringify
の2番目のパラメーターである replacer function を使用して、既にシリアル化されたオブジェクトを除外します。
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;
});
他のコメントで正しく指摘されているように、このコードは「再帰的」オブジェクトだけでなく、「見られた」オブジェクトをすべて削除します。
たとえば、次の場合:
a = {x:1};
obj = [a, a];
結果は不正確になります。構造がこのような場合、Crockfordの decycle がより良いオプションです。
周期構造を検出し、それらをデコードおよびエンコードできるGitHub Gistを作成しました: https://Gist.github.com/Hoff97/9842228
変換するには、JSONE.stringify/JSONE.parseを使用するだけです。また、関数をデエンコードおよびエンコードします。これを無効にする場合は、32〜48行目と61〜85行目を削除します。
var strg = JSONE.stringify(cyclicObject);
var cycObject = JSONE.parse(strg);
ここでフィドルの例を見つけることができます:
ずっと節約でき、cycleオブジェクトがどこにあったかを示します。
<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>
生産する
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
}
);
}
それ以外の場合、配列オブジェクトの整数値は切り捨てられます。つまり、[[08.11.2014 12:30:13、1095]] 1095は095に減少します。
繰り返しオブジェクトをシリアル化して、Stringのようなserializename属性に保存するとクラスを復元できるgithubプロジェクトも作成します
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
編集:NPMのスクリプトを変換しました https://github.com/bormat/borto_circular_serialize と関数名をフランス語から英語に変更しました。