প্রোটোটাইপ.জেএস এর সাথে জেএসএন.স্ট্রিংফাই () অ্যারে উদ্ভটতা


89

আমি আমার জসন সিরিয়ালাইজেশনে কী ভুল হয়েছে তা সনাক্ত করার চেষ্টা করছি, আমার অ্যাপ্লিকেশনটির বর্তমান সংস্করণটি পুরানো ও পুরনো সহ পেয়েছি এবং JSON.stringify () যেভাবে কাজ করছে (json.org থেকে জেএসএন লাইব্রেরি ব্যবহার করে) তাতে কিছু আশ্চর্যজনক পার্থক্য খুঁজে পাচ্ছি )।

আমার অ্যাপ্লিকেশনটির পুরানো সংস্করণে:

 JSON.stringify({"a":[1,2]})

আমাকে এই দেয়;

"{\"a\":[1,2]}"

নতুন সংস্করণে,

 JSON.stringify({"a":[1,2]})

আমাকে এই দেয়;

"{\"a\":\"[1, 2]\"}"

নতুন সংস্করণে অ্যারে বন্ধনীগুলির কাছাকাছি একই লাইব্রেরিটি কোটায় রাখার জন্য কী পরিবর্তন হতে পারে?


4
দেখে মনে হচ্ছে এটি প্রোটোটাইপ লাইব্রেরির সাথে বিরোধ, যা আমরা নতুন সংস্করণে প্রবর্তন করেছি। প্রোটোটাইপের অধীনে কোন অ্যারে সমন্বিত একটি জসন বস্তুকে কীভাবে শক্তিশালী করা যায় সে সম্পর্কে কোনও ধারণা?
মরগানকোডস

26
যে কারণে লোকেরা বিশ্বজুড়ে অন্তর্নির্মিত বস্তুগুলির সাথে জড়িত হওয়া থেকে বিরত থাকে (প্রোটোটাইপ ফ্রেমওয়ার্ক যেমন করে)
জেরার্ডো লিমা

উত্তর:


82

যেহেতু JSON.stringify কিছু ব্রাউজারের সাথে ইদানীং শিপিং করছে, তাই আমি প্রোটোটাইপের টোজেএসনের পরিবর্তে এটি ব্যবহারের পরামর্শ দেব। তারপরে আপনি উইন্ডোটি পরীক্ষা করে দেখতে পারেন J JSON && window.JSON.stringify এবং কেবল json.org লাইব্রেরি অন্যথায় (এর মাধ্যমে document.createElement('script')…) অন্তর্ভুক্ত করবেন। অসম্পূর্ণতাগুলি সমাধান করতে, ব্যবহার করুন:

if(window.Prototype) {
    delete Object.prototype.toJSON;
    delete Array.prototype.toJSON;
    delete Hash.prototype.toJSON;
    delete String.prototype.toJSON;
}

আপনার নিজের কোডে
উইন্ডোটি

এটি এমনটি হতে পারে তবে তার পরেও পুরো স্ক্রিপ্ট ফাইলটি লোড করতে হবে যদি এটি প্রয়োজন না হয়।
রাফেল শোয়েকার্ট

11
প্রকৃতপক্ষে, প্রশ্নের সাথে মোকাবিলা করার জন্য একমাত্র বিবৃতিটি হ'ল: অ্যারে.প্রোটোটাইপ.টোজসন
জিন ভিনসেন্ট

4
তোমাকে অনেক ধন্যবাদ. আমি বর্তমানে যে সংস্থাটির জন্য কাজ করি বর্তমানে এটি আমাদের কোডের বেশিরভাগ ক্ষেত্রে প্রোটোটাইপ ব্যবহার করে এবং আরও আধুনিক গ্রন্থাগারগুলি ব্যবহারের জন্য এটি জীবন রক্ষাকারী ছিল, অন্যথায় সবকিছু ভেঙে যাচ্ছিল।
krob

4
আমি DAYS এর জন্য এই উত্তরটির সন্ধান করছি এবং এটি বের করার চেষ্টা করে দুটি ভিন্ন এসও প্রশ্ন পোস্ট করেছি। এটি তৃতীয় টাইপ করার সময় এটি সম্পর্কিত প্রশ্ন হিসাবে দেখেছি। তোমাকে অনেক ধন্যবাদ!
ম্যাথু হার্বস্ট

80

ECMAScript 5 এবং তারপরে ( পৃষ্ঠা 201 - JSON অবজেক্ট, সিউডো কোড পৃষ্ঠা 205) এ সংজ্ঞায়িত JSON.stringify () ফাংশনটি, যখন বস্তুগুলিতে উপলভ্য থাকে তখন to JSON () ফাংশনটি ব্যবহার করে।

প্রোটোটাইপ.জে (বা আপনি যে অন্য গ্রন্থাগারটি ব্যবহার করছেন) একটি অ্যারে.প্রোটোটাইপ.টোজেএসন () ফাংশন সংজ্ঞায়িত করে, অ্যারে প্রথমে অ্যারে.প্রোটোটাইপ.টোজেএসএন () ব্যবহার করে স্ট্রিংগুলিতে রূপান্তরিত হয় তারপরে JSON.stringify () দ্বারা উদ্ধৃত স্ট্রিং, তাই অ্যারের আশেপাশে ভুল অতিরিক্ত উদ্ধৃতি।

সমাধান তাই সরাসরি-সামনের এবং তুচ্ছ (এটি রাফেল শোয়েকার্টের উত্তরের সরল সংস্করণ):

delete Array.prototype.toJSON

এটি লাইব্রেরিগুলিতে অবশ্যই পার্শ্ব প্রতিক্রিয়া তৈরি করে যা অ্যারেগুলির জন্য একটি জেএসওএন () ফাংশন বৈশিষ্ট্যের উপর নির্ভর করে। তবে আমি ECMAScript 5 এর সাথে অসঙ্গতি বিবেচনা করে এটিকে একটি সামান্য অসুবিধা মনে করি।

এটি অবশ্যই লক্ষণীয় যে ECMAScript 5 এ সংজ্ঞায়িত JSON অবজেক্টটি দক্ষতার সাথে আধুনিক ব্রাউজারগুলিতে প্রয়োগ করা হয়েছে এবং অতএব সর্বোত্তম সমাধান হ'ল স্ট্যান্ডার্ডের সাথে মানানসই এবং বিদ্যমান লাইব্রেরি সংশোধন করা।


4
এটি অ্যারের অতিরিক্ত উদ্ধৃতি দিয়ে কী চলছে তার সর্বাধিক সংক্ষিপ্ত উত্তর।
tmarthal

15

একটি সম্ভাব্য সমাধান যা অন্যান্য প্রোটোটাইপ নির্ভরতাগুলিকে প্রভাবিত করে না তা হ'ল:

var _json_stringify = JSON.stringify;
JSON.stringify = function(value) {
    var _array_tojson = Array.prototype.toJSON;
    delete Array.prototype.toJSON;
    var r=_json_stringify(value);
    Array.prototype.toJSON = _array_tojson;
    return r;
};

এটি JSON.stringify এর সাথে অ্যারে থেকে JSON অসম্পূর্ণতার যত্ন নেয় এবং অন্যান্য প্রোটোটাইপ লাইব্রেরিগুলিতে এটি নির্ভর করতে পারে বলে টস জেএসওএন কার্যকারিতাও বজায় রাখে।


আমি এই স্নিপেটটি একটি ওয়েবসাইটে ব্যবহার করেছি। এটি সমস্যা সৃষ্টি করছে। এটি অ্যারে'র জেএসওএন বৈশিষ্ট্যটিকে সংজ্ঞায়িত করার ফলাফল দেয়। কোন পয়েন্টার?
সৌরভ

4
দয়া করে নিশ্চিত করুন যে JSON.stringify পুনরায় সংজ্ঞায়িত করার জন্য উপরের স্নিপেট ব্যবহার করার আগে আপনার অ্যারে.প্রোটোটাইপ.টোজেএসন সংজ্ঞায়িত হয়েছে। এটি আমার পরীক্ষায় ভাল কাজ করে।
আক্কিশোর

4
আমি গুটিয়ে রাখলাম if(typeof Prototype !== 'undefined' && parseFloat(Prototype.Version.substr(0,3)) < 1.7 && typeof Array.prototype.toJSON !== 'undefined')। এটা কাজ করেছে.
সৌরভ

4
দুর্দান্ত প্রোটোটাইপ 1.7 অবধি কেবল এটিই একটি সমস্যা। দয়া করে
উন্নত

4
সমস্যাটি <1.7 সংস্করণগুলির জন্য
সৌরভ

9

কিছুটা আরও নির্ভুল করতে সম্পাদনা করুন:

কোডের সমস্যা কীটি JSON.org এর JSON লাইব্রেরিতে রয়েছে (এবং ECMAScript 5 এর JSON অবজেক্টের অন্যান্য বাস্তবায়ন):

if (value && typeof value === 'object' &&
  typeof value.toJSON === 'function') {
  value = value.toJSON(key);
}

সমস্যাটি হ'ল প্রোটোটাইপ গ্রন্থাগারটি একটি জেএসওএন পদ্ধতি অন্তর্ভুক্ত করতে অ্যারে প্রসারিত করে, যা JSON অবজেক্ট উপরের কোডটিতে কল করবে। যখন JSON অবজেক্ট অ্যারের মানটিকে হিট করে তখন এটি অ্যারে JSON এ কল করে যা প্রোটোটাইপে সংজ্ঞায়িত হয় এবং সেই পদ্ধতিটি অ্যারের স্ট্রিং সংস্করণ দেয়। সুতরাং অ্যারের বন্ধনীগুলির চারপাশে উদ্ধৃতিগুলি।

আপনি যদি অ্যারে অবজেক্ট থেকে জেএসএন মোছা করেন তবে জাসন লাইব্রেরিটি সঠিকভাবে কাজ করা উচিত। অথবা, কেবল জেএসএন লাইব্রেরি ব্যবহার করুন।


4
এটি লাইব্রেরিতে কোনও ত্রুটি নয়, কারণ এটি হ'ল JSON.stringify () ECMAScript 5 এ সংজ্ঞায়িত করা হয়েছে prot সমস্যাটি প্রোটোটাইপ.জেএস নিয়ে রয়েছে এবং সমাধানটি হ'ল: অ্যারে.প্রোটোটাইপ.টোজেসন মুছুন এটির কিছু দিক থাকবে প্রোটোটাইপ টু জেএসএন সিরিয়ালাইজেশনের জন্য প্রভাবগুলি, তবে প্রোটোটাইপের সাথে ইসকামাস্ক্রিপ্ট ৫-এর অসম্পূর্ণতা সম্পর্কে আমি এই অপ্রাপ্তবয়স্ককে খুঁজে পেয়েছি
জিন ভিনসেন্ট

প্রোটোটাইপ লাইব্রেরি অবজেক্ট.প্রোটোটাইপ না করে অ্যারে.প্রোটোটাইপ প্রসারিত করে, যদিও জাভাস্ক্রিপ্টে টাইপফ অ্যারে এছাড়াও "অবজেক্ট" প্রদান করে, তাদের একই "কনস্ট্রাক্টর" এবং প্রোটোটাইপ নেই। সমস্যাটি সমাধান করার জন্য আপনার দরকার: "অ্যারে.প্রোটোটাইপ.টোজেএসন মুছুন;"
জিন ভিনসেন্ট

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

প্রোটোটাইপ দীর্ঘদিন ধরে "অবজেক্ট.প্রোটোটাইপ" প্রসারিত করা বন্ধ করেছে (ইস্যুগুলির ক্ষেত্রে এড়াতে কোনও সংস্করণ যদিও আমি মনে করি না)। এটি কেবলমাত্র নামস্থান হিসাবে অবজেক্টের স্থির বৈশিষ্ট্যগুলি (যা অনেক বেশি নিরাপদ) প্রসারিত করে: api.prototypejs.org/language/Object
জিন ভিনসেন্ট

জিন, আসলে এটি ঠিক লাইব্রেরির একটি বাগ। যদি কোনও জিনিসের জেএসওএন থাকে, তবে অবশ্যই এটি কল করা উচিত এবং এর ফলাফল অবশ্যই ব্যবহার করা উচিত তবে এটি উদ্ধৃত হওয়া উচিত নয়।
grr

4

আমি মনে করি প্রোটোটাইপ লোড হওয়ার ঠিক পরে এটির অন্তর্ভুক্ত করা আরও ভাল সমাধান হবে

JSON = JSON || {};

JSON.stringify = function(value) { return value.toJSON(); };

JSON.parse = JSON.parse || function(jsonsring) { return jsonsring.evalJSON(true); };

এটি প্রোটোটাইপ ফাংশনটিকে স্ট্যান্ডার্ড JSON.stringify () এবং JSON.parse () হিসাবে উপলভ্য করে তোলে তবে এটি যদি পাওয়া যায় তবে দেশীয় JSON.parse () রাখে, সুতরাং এটি পুরানো ব্রাউজারগুলির সাথে জিনিসগুলিকে আরও সুসংগত করে তোলে।


'মান' এ পাস করা কোনও অবজেক্ট হলে JSON.stringify সংস্করণটি কাজ করে না। পরিবর্তে আপনার এটি করা উচিত: JSON.stringify = ফাংশন (মান) Ob ফেরত অবজেক্ট.টোজেএসএন (মান); };
আক্কিশোর

2

আমি প্রোটোটাইপের সাথে তেমন সাবলীল নই, তবে এটি ডক্সে দেখেছি :

Object.toJSON({"a":[1,2]})

আমি নিশ্চিত না যদিও বর্তমান এনকোডিংয়ের ক্ষেত্রে এটি একই সমস্যা হয়েছে কিনা।

প্রোটোটাইপ সহ জেএসএন ব্যবহার করার বিষয়ে একটি দীর্ঘ টিউটোরিয়াল রয়েছে


2

এটি একই কোডের জন্য আমি ব্যবহার করেছি:

function stringify(object){
      var Prototype = window.Prototype
      if (Prototype && Prototype.Version < '1.7' &&
          Array.prototype.toJSON && Object.toJSON){
              return Object.toJSON(object)
      }
      return JSON.stringify(object)
}

প্রোটোটাইপ উপস্থিত রয়েছে কিনা তা আপনি পরীক্ষা করে দেখুন, তারপরে আপনি সংস্করণটি পরীক্ষা করেন। যদি পুরানো সংস্করণ অন্য সমস্ত ক্ষেত্রে অবজেক্ট. টোজেএসন (যদি সংজ্ঞায়িত হয়) ব্যবহার করে তবে JSON.stringify () এ পড়ে


1

আমি এটির সাথে কীভাবে আচরণ করছি তা এখানে।

var methodCallString =  Object.toJSON? Object.toJSON(options.jsonMethodCall) :  JSON.stringify(options.jsonMethodCall);

1

আমার সহনশীল সমাধানটি JSON স্ট্রিংফাইয়ের জন্য অ্যারে.প্রোটোটাইপ.টোজেএসন ক্ষতিকারক কিনা তা যাচাই করে এবং আশেপাশের কোডটি প্রত্যাশার মতো কাজ করতে দেওয়া সম্ভব রাখে:

var dummy = { data: [{hello: 'world'}] }, test = {};

if(Array.prototype.toJSON) {
    try {
        test = JSON.parse(JSON.stringify(dummy));
        if(!test || dummy.data !== test.data) {
            delete Array.prototype.toJSON;
        }
    } catch(e) {
        // there only hope
    }
}

1

লোকেরা যেমন উল্লেখ করেছে, এটি প্রোটোটাইপ.জেএস এর কারণে - বিশেষত 1.7 এর আগে সংস্করণ। আমারও একই অবস্থা ছিল তবে প্রোটোটাইপ.জেএস ছিল কিনা তা পরিচালনা করে এমন কোড থাকতে হয়েছিল; এর অর্থ আমি আরে.প্রোটোটাইপ.টোজেএসনকে কেবল মুছতে পারি না কারণ এতে কী নির্ভর করে তা আমি নিশ্চিত নই। এই পরিস্থিতির জন্য এটিই আমি সেরা সমাধানটি নিয়ে এসেছি:

function safeToJSON(item){ 
    if ([1,2,3] === JSON.parse(JSON.stringify([1,2,3]))){
        return JSON.stringify(item); //sane behavior
    } else { 
        return item.toJSON(); // Prototype.js nonsense
    }
}

আশা করি এটি কারও সাহায্য করবে।


0

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

(function (undefined) { // This is just to limit _json_stringify to this scope and to redefine undefined in case it was
  if (true ||typeof (Prototype) !== 'undefined') {
    // First, ensure we can access the prototype of an object.
    // See http://stackoverflow.com/questions/7662147/how-to-access-object-prototype-in-javascript
    if(typeof (Object.getPrototypeOf) === 'undefined') {
      if(({}).__proto__ === Object.prototype && ([]).__proto__ === Array.prototype) {
        Object.getPrototypeOf = function getPrototypeOf (object) {
          return object.__proto__;
        };
      } else {
        Object.getPrototypeOf = function getPrototypeOf (object) {
          // May break if the constructor has been changed or removed
          return object.constructor ? object.constructor.prototype : undefined;
        }
      }
    }

    var _json_stringify = JSON.stringify; // We save the actual JSON.stringify
    JSON.stringify = function stringify (obj) {
      var obj_prototype = Object.getPrototypeOf(obj),
          old_json = obj_prototype.toJSON, // We save the toJSON of the object
          res = null;
      if (old_json) { // If toJSON exists on the object
        obj_prototype.toJSON = undefined;
      }
      res = _json_stringify.apply(this, arguments);
      if (old_json)
        obj_prototype.toJSON = old_json;
      return res;
    };
  }
}.call(this));

এটি জটিল বলে মনে হচ্ছে তবে বেশিরভাগ ব্যবহারের ক্ষেত্রে এটি হ'ল জটিল। মূল ধারণাটি আর্গুমেন্ট হিসাবে পাস করা বস্তুটি থেকে JSON.stringifyসরানোর জন্য ওভাররাইড করছে toJSON, তারপরে পুরানোটিকে কল করুন JSON.stringifyএবং শেষ পর্যন্ত এটি পুনরুদ্ধার করুন।

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