চক্রীয় বস্তুর মান ধারণ করে এমন বস্তু সিরিয়ালাইজ করা


151

আমার একটি অবজেক্ট (পার্স ট্রি) রয়েছে যার মধ্যে শিশু নোড রয়েছে যা অন্যান্য নোডের উল্লেখ।

আমি এই অবজেক্টটি ব্যবহার করে সিরিয়ালিয়াল করতে চাই JSON.stringify(), তবে আমি পেয়েছি

প্রকারের ত্রুটি: চক্রীয় বস্তুর মান

কারণ আমি কনস্ট্রাক্টস উল্লেখ করেছি।

আমি কীভাবে এটিকে ঘিরে কাজ করতে পারি? অন্যান্য নোডের এই রেফারেন্সগুলি সিরিয়ালযুক্ত অবজেক্টে প্রতিনিধিত্ব করা হয় বা না তা আমার বিবেচ্য নয়।

অন্যদিকে, যখন এই বৈশিষ্ট্যগুলি তৈরি করা হচ্ছে তখন বস্তু থেকে তাদের সরিয়ে ফেলা ক্লান্তিকর বলে মনে হচ্ছে এবং আমি পার্সারে (নারিসিসাস) পরিবর্তন করতে চাই না।


1
আমরা কিছু কোড ছাড়াই আপনাকে সহায়তা করতে পারি না। আপনি এটিটি সিরিয়াল করতে যে জেএস ব্যবহার করেন তার সাথে দয়া করে আপনার অবজেক্টের প্রাসঙ্গিক বিট এবং / অথবা JSON আউটপুট পোস্ট করুন।
বোজাঙ্গলেস

1
অভ্যন্তরীণ উল্লেখগুলি যে বৈশিষ্ট্যগুলিতে কিছু উপসর্গ যুক্ত করতে সক্ষম?
Wheresrhys

@ লৌইক cycle.jsএখানে উত্তর হিসাবে ডগলাস ক্রকফোর্ডের কাছে রাখা মূল্যবান হবে , কারণ এটি অনেক ক্ষেত্রেই সবচেয়ে উপযুক্ত সমাধান। এই উত্তরটি পোস্ট করা আপনার পক্ষে উপযুক্ত বলে মনে হচ্ছে, যেহেতু আপনি এটির প্রথম উল্লেখ করছেন (নীচে আপনার মন্তব্যে)। যদি আপনি নিজের উত্তর হিসাবে এটি পোস্ট করার মতো মনে করেন না, তবে অবশেষে আমি এটি করব।
জেরেমি ব্যাংকগুলি


1
আমি আশা করি জেএসওন স্মার্ট হয়ে উঠবে, বা এটিকে সমাধান করার সহজতর উপায়। সাধারণ (!) ডিবাগিং উদ্দেশ্যে ইমো জন্য সমাধানগুলি খুব ঝামেলার।
ব্লু

উত্তর:


220

দ্বিতীয় প্যারামিটার ব্যবহার করুন stringify, replacer ফাংশন ইতিমধ্যে ধারাবাহিকভাবে বস্তু অগ্রাহ্য করা হবে:

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

http://jsfiddle.net/mH6cJ/38/

অন্যান্য মন্তব্যে সঠিকভাবে নির্দেশিত হিসাবে, এই কোডটি প্রতিটি "দেখা" অবজেক্টকে সরিয়ে দেয়, কেবল "পুনরাবৃত্ত" নয় "

উদাহরণস্বরূপ, এর জন্য:

a = {x:1};
obj = [a, a];

ফলাফলটি ভুল হবে। যদি আপনার কাঠামোটি এর মতো হয় তবে আপনি ক্রকফোর্ডের ডেস্কিল বা এটি (সহজ) ফাংশনটি ব্যবহার করতে চাইতে পারেন যা কেবল পুনরাবৃত্ত উল্লেখগুলি নাল দিয়ে প্রতিস্থাপন করে:

function decycle(obj, stack = []) {
    if (!obj || typeof obj !== 'object')
        return obj;
    
    if (stack.includes(obj))
        return null;

    let s = stack.concat([obj]);

    return Array.isArray(obj)
        ? obj.map(x => decycle(x, s))
        : Object.fromEntries(
            Object.entries(obj)
                .map(([k, v]) => [k, decycle(v, s)]));
}

//

let a = {b: [1, 2, 3]}
a.b.push(a);

console.log(JSON.stringify(decycle(a)))


3
আঃ সুন্দর! ধন্যবাদ, আমি এটি চেষ্টা করতে যাচ্ছি। আমি ডগলাস ক্রকফোর্ড ( github.com/douglascrockford/JSON-js/blob/master/यकल.js ) দ্বারা তৈরি একটি সমাধান পেয়েছি , তবে আমি যে লাইসেন্সটি দিয়ে চলেছি সে সম্পর্কে আমি অনিশ্চিত, আপনার বর্ণিত সহজ সমাধানটি নিখুঁত হবে!
লুইক ডুরোস

3
@ লুইকডুরোস লাইসেন্সটি "পাবলিক ডোমেন"। অর্থ, আপনি এটি দিয়ে যা কিছু করতে পারেন।
এটস গোরাল

1
এই কোডটি সাইক্লিং লুপগুলি তৈরি করে, ব্যবহার থেকে সাবধান থাকুন, খুব সম্ভাব্য আপনার অ্যাপ্লিকেশনটিকে ক্র্যাশ করে। সঠিক সেমিকোলন প্রয়োজন এবং ইভেন্ট অবজেক্টে ব্যবহারযোগ্য নয়!
ওল সেন

3
এটি কেবলমাত্র চক্রীয় রেফারেন্সের চেয়েও বেশি সরিয়ে দেয় - এটি কেবল একবারের বেশি দেখা যায় এমন কিছু সরিয়ে দেয়। ইতিমধ্যে সিরিয়ালযুক্ত অবজেক্টটি নতুন অবজেক্টের "পিতামাতা" না হলে আপনি এটিকে মুছবেন না
জিও

1
ভাল উত্তর! আমি এটিকে কিছুটা সংশোধন করেছি, ফাংশনটিকে একটি পুনরাবৃত্ত ফাংশনে পরিবর্তন করেছি, যাতে শিশু-অবজেক্টগুলি পিতামাতার অবজেক্টগুলিকে ক্লোন করার উপযোগী করে তোলে।
হোল্ডঅফহাঙ্গার

2

আমি একটি গিটহাব গিস্ট তৈরি করেছি যা চক্রাকার কাঠামোগুলি সনাক্ত করতে সক্ষম করে এবং এগুলি এনকোড করে এবং https://gist.github.com/Hoff97/9842228

রূপান্তর করতে কেবল JSONE.stringify / JSONE.parse ব্যবহার করুন। এটি ফাংশনগুলি ডি-এবং এনকোড করে। আপনি যদি এটি অক্ষম করতে চান তবে কেবল 32-48 এবং 61-85 লাইনগুলি সরিয়ে দিন।

var strg = JSONE.stringify(cyclicObject);
var cycObject = JSONE.parse(strg);

আপনি এখানে একটি উদাহরণ বেড়ান খুঁজে পেতে পারেন:

http://jsfiddle.net/hoff97/7UYd4/


2

এটি এক ধরনের বিকল্প-উত্তর, তবে যেহেতু প্রচুর লোক এখানে আসবে তাদের বৃত্তাকার বস্তুগুলি ডিবাগ করছে এবং কোডের একগুচ্ছকে টান না দিয়ে এটি করার সত্যিই দুর্দান্ত উপায় নেই, এখানে যায়।

এক বৈশিষ্ট্য যা সুপরিচিত হিসাবে হিসাবে নয় JSON.stringify()হয় console.table()। কেবল কল করুন console.table(whatever);এবং এটি ভেরিয়েবলের বিষয়বস্তুটি অনুধাবন করার পরিবর্তে এটি বেশ সহজ এবং সুবিধাজনক করে টেবুলার বিন্যাসে কনসোলে ভেরিয়েবল লগ করবে।


1

অনেক বেশি সেভার এবং এটি দেখায় যে কোনও চক্রের অবজেক্ট ছিল।

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

তবে এই কোডটিতে এখনও একটি সমস্যা রয়েছে যদি কেউ obj.b=this'যদি কোনও অবৈধ অবৈধ সুযোগ তৈরি করে কীভাবে খুব দীর্ঘ ক্যালকগুলি রোধ thisকরতে হয় তা যদি জানতে পারে তবে এখানে দেখতে খুব ভাল লাগবে
ওল সেন

2
এটি হওয়া উচিতseen.indexOf(v) != -1

1

আমি একটি গিথুব প্রজেক্ট তৈরি করেছি যা চক্রাকার অবজেক্টটি সিরিয়ালাইজ করতে পারে এবং ক্লাসটি পুনরুদ্ধার করতে পারে যদি আপনি এটি স্ট্রিংয়ের মতো সিরিয়ালীকরণ বৈশিষ্ট্যে সংরক্ষণ করেন

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

সম্পাদনা: আমি আমার স্ক্রিপ্টটি এনপিএম https://github.com/bormat/borto_circular_serialize এর জন্য রূপান্তর করেছি এবং আমার ফরাসি থেকে ইংরেজী ভাষায় ফাংশনের নাম পরিবর্তন হয়েছে।


এই উদাহরণটি গিস্টের সাথে খাপ খায় না। গিস্টের ত্রুটি রয়েছে।
আর্নস্ট আর্নস্ট

দুর্দান্ত ধারণা - তবে একবার এটি প্রস্তুত করুন :-) আপনি যদি এনপিএম এ এটি বিতরণ করেন তবে সম্ভবত আপনি এটির জন্য টাইপগুলিও বিকাশ করতে পারেন, এটি সম্ভবত বেশ জনপ্রিয় হয়ে উঠেছে।
পিটারহ - মনিকা পুনরায় ইনস্টল করুন

1

চক্রীয় রেফারেন্স সহ ডেটা স্ট্রাকচারের উদাহরণ এখানে রয়েছে: toolshedCY

function makeToolshed(){
    var nut = {name: 'nut'}, bolt = {name: 'bolt'};
    nut.needs = bolt; bolt.needs = nut;
    return { nut: nut, bolt: bolt };
}

আপনি যখন সাইক্লিক রেফারেন্সগুলি কেপ করতে চান (যখন আপনি "নুকিং" না দিয়ে ডিসরিয়াল করবেন তখন সেগুলি পুনরুদ্ধার করুন), আপনার কাছে দুটি পছন্দ আছে, যা আমি এখানে তুলনা করব। প্রথমটি হ'ল ডগলাস ক্রকফোর্ডের চক্র .js , দ্বিতীয়টি আমার সাইবেরিয়া প্যাকেজ। উভয়ই প্রথম "ডাইসাইক্লিং" অবজেক্ট দ্বারা কাজ করে, অর্থাত্, একই তথ্য সম্বলিত অন্য কোনও অবজেক্ট (কোনও চক্রীয় রেফারেন্স ছাড়াই) নির্মাণ করে। "

মিঃ ক্রকফোর্ড প্রথম যান:

JSON.decycle(makeToolshed())

JSON_decycleMakeToolshed

আপনি দেখতে পাচ্ছেন, জেএসএনের নেস্টেড কাঠামোটি ধরে রাখা হয়েছে, তবে একটি নতুন জিনিস রয়েছে যা বিশেষ $refসম্পত্তি যুক্ত objects আসুন দেখুন কিভাবে এটি কাজ করে।

root = makeToolshed();
[root.bolt === root.nut.needs, root.nut.needs.needs === root.nut]; // retutrns [true,true]

ডলারের চিহ্নটি মূলকে বোঝায়। .boltথাকার $refআমাদেরকে বলে যে .boltএকটি "ইতিমধ্যে দেখা" বস্তু, এবং যে বিশেষ সম্পত্তির মান (এখানে স্ট্রিং $ [ "বাদাম"] [ "চাহিদা"]) আমাদেরকে যেখানে, প্রথম দেখতে বলে ===উপরে। একইভাবে দ্বিতীয় $refএবং দ্বিতীয়টির জন্য ===

ক্লোনিং কাজ করে কিনা তা দেখার জন্য আসুন একটি গভীর গভীর সমতা পরীক্ষা (যথা এই প্রশ্নেরdeepGraphEqual গ্রহণযোগ্য উত্তর থেকে অ্যান্ডারস কাসরগের কার্যকারিতা ) ব্যবহার করুন।

root = makeToolshed();
clone = JSON.retrocycle(JSON.decycle(root));
deepGraphEqual(root, clone) // true
serialized = JSON.stringify(JSON.decycle(root));
clone2 = JSON.retrocycle(JSON.parse(serialized));
deepGraphEqual(root, clone2); // true

এখন, সাইবেরিয়া:

JSON.Siberia.forestify(makeToolshed())

JSON_Siberia_forestify_makeToolshed

সাইবেরিয়া "ক্লাসিক" জেএসএন, কোনও নেস্টেড কাঠামো নকল করার চেষ্টা করে না। অবজেক্ট গ্রাফটি "ফ্ল্যাট" পদ্ধতিতে বর্ণনা করা হয়। অবজেক্ট গ্রাফের প্রতিটি নোডকে সমতল গাছে রূপান্তরিত করা হয় (কেবলমাত্র পূর্ণসংখ্যার মানগুলির সাথে প্লেইন কী মান জোড়ের তালিকা) যা .forest.সূচকের শূন্যের একটি এন্ট্রি , আমরা মূল বস্তুটি খুঁজে পাই, উচ্চতর সূচকগুলিতে, আমরা অন্যান্য নোডগুলি খুঁজে পাই অবজেক্ট গ্রাফ এবং নেতিবাচক মানগুলি (বনের কিছু গাছের কিছু কী এর) atomsঅ্যারেতে নির্দেশ করে , (যা টাইপ অ্যারে দিয়ে টাইপ করা হয়, তবে আমরা এখানে টাইপিংয়ের বিশদটি এড়িয়ে যাব)। সমস্ত টার্মিনাল নোডগুলি পরমাণু টেবিলের মধ্যে রয়েছে, সমস্ত নন-টার্মিনাল নোডগুলি বনের টেবিলে রয়েছে এবং আপনি অবিলম্বে দেখতে পাবেন যে অবজেক্টের গ্রাফটি রয়েছে কতগুলি নোড, যথা forest.length। এটি পরীক্ষা করে দেখা যাক:

root = makeToolshed();
clone = JSON.Siberia.unforestify(JSON.Siberia.forestify(root));
deepGraphEqual(root, clone); // true
serialized = JSON.Siberia.stringify(JSON.Siberia.forestify(root));
clone2 = JSON.Siberia.unforestify(JSON.Siberia.unstringify(serialized));
deepGraphEqual(root, clone2); // true

তুলনা

পরে বিভাগ যুক্ত হবে।


0
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-এ কমে যায়।


পেয়ে RefrenceError: পরিবর্তনশীল খুঁজে পাওয়া যাচ্ছে না:: _
অমিত পান্ড্য

আপনার কোড ঠিক করুন।
অ্যানাস্ট্যাসিওস মোরাটাইস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.