JSON স্ট্রিংটিকে জাভাস্ক্রিপ্টের একটি বিশেষ বস্তুর প্রোটোটাইপে পার্স করুন


173

আমি জানি কিভাবে কীভাবে JSON স্ট্রিংকে পার্স করতে এবং এটিকে একটি জাভাস্ক্রিপ্ট অবজেক্টে রূপান্তর করতে হবে। আপনি JSON.parse()আধুনিক ব্রাউজারগুলিতে (এবং আই 9 +) ব্যবহার করতে পারেন ।

এটি দুর্দান্ত, তবে আমি কীভাবে সেই জাভাস্ক্রিপ্ট অবজেক্টটি নিয়ে একটি নির্দিষ্ট জাভাস্ক্রিপ্ট অবজেক্টে (অর্থাত্ একটি নির্দিষ্ট প্রোটোটাইপ সহ) রূপান্তর করতে পারি ?

উদাহরণস্বরূপ, ধরুন আপনার কাছে রয়েছে:

function Foo()
{
   this.a = 3;
   this.b = 2;
   this.test = function() {return this.a*this.b;};
}
var fooObj = new Foo();
alert(fooObj.test() ); //Prints 6
var fooJSON = JSON.parse({"a":4, "b": 3});
//Something to convert fooJSON into a Foo Object
//....... (this is what I am missing)
alert(fooJSON.test() ); //Prints 12

আবার, আমি কীভাবে জেএসএন স্ট্রিংটিকে জেনেরিক জাভাস্ক্রিপ্ট অবজেক্টে রূপান্তর করব তা ভাবছি না। আমি জেএসএন স্ট্রিংকে কীভাবে "ফু" অবজেক্টে রূপান্তর করতে চাই তা জানতে চাই। অর্থাত, আমার অবজেক্টের এখন একটি ফাংশন 'পরীক্ষা' এবং বৈশিষ্ট্যগুলি 'এ' এবং 'বি' হওয়া উচিত।

আপডেট কিছু গবেষণা করার পরে, আমি এই ভেবেছিলাম ...

Object.cast = function cast(rawObj, constructor)
{
    var obj = new constructor();
    for(var i in rawObj)
        obj[i] = rawObj[i];
    return obj;
}
var fooJSON = Object.cast({"a":4, "b": 3}, Foo);

কাজ করবে?

আপডেট মে, 2017 : এটি করার "আধুনিক" উপায়টি হল Object.assign, তবে এই ফাংশনটি আইই 11 বা পুরানো অ্যান্ড্রয়েড ব্রাউজারগুলিতে উপলব্ধ নয়।


উত্তর:


124

বর্তমানের উত্তরগুলিতে প্রচুর হ্যান্ড-রোলড বা লাইব্রেরি কোড রয়েছে। এই প্রয়োজন হয় না.

  1. JSON.parse('{"a":1}')একটি সরল অবজেক্ট তৈরি করতে ব্যবহার করুন ।

  2. প্রোটোটাইপ সেট করতে মানকযুক্ত একটি ফাংশন ব্যবহার করুন:

    • Object.assign(new Foo, { a: 1 })
    • Object.setPrototypeOf({ a: 1 }, Foo.prototype)

2
আইজিস এবং পুরানো অ্যান্ড্রয়েড ব্রাউজার সহ পুরানো ব্রাউজারগুলিতে অবজেক্ট.সেসাইন উপলভ্য নয়। kangax.github.io/compat-table/es6/…
বিমিনিয়ার

5
ব্যবহারের বিরুদ্ধে একটি বড় সতর্কতাও রয়েছে Object.setPrototypeOf(...)বিকাশকারী.মোজিলা.আর.ইন-
ইউএস

@ সিমোনএপস্ক্যাম্প এই কোডটি কার্যকর করে না। আপনার ইউআরএল, setPrototypeOfসম্পত্তি বিবরণকারী হিসাবে দ্বিতীয় প্যারামিটার পরীক্ষা করুন ।
এরিক ভ্যান ভেলজেন

6
প্রোটোটাইপ সেট করার সমাধান সমাধানে কাজ করে না যদি এমন কিছু সম্পত্তি থাকে যা প্রোটোটাইপ থাকা দরকার। অন্য কথায়: এটি কেবল মাত্রা স্তরক্রমের প্রথম স্তরের সমাধান করে।
ভোজটা

2
নীচে আমার সমাধানটি দেখুন যা অবজেক্ট.অ্যাসাইন (..) পুনরাবৃত্তির সাথে প্রয়োগ করে যা স্বয়ংক্রিয়ভাবে বৈশিষ্ট্যগুলি সমাধান করতে পারে (আগাম কিছু সরবরাহিত তথ্য সরবরাহ করা হয়েছে)
আমাদের 16 ই

73

নীচে একটি উদাহরণ দেখুন (এই উদাহরণটি দেশীয় জেএসওএন অবজেক্ট ব্যবহার করে)। আমার পরিবর্তনগুলি ক্যাপিটালগুলিতে মন্তব্য করা হয়েছে:

function Foo(obj) // CONSTRUCTOR CAN BE OVERLOADED WITH AN OBJECT
{
    this.a = 3;
    this.b = 2;
    this.test = function() {return this.a*this.b;};

    // IF AN OBJECT WAS PASSED THEN INITIALISE PROPERTIES FROM THAT OBJECT
    for (var prop in obj) this[prop] = obj[prop];
}

var fooObj = new Foo();
alert(fooObj.test() ); //Prints 6

// INITIALISE A NEW FOO AND PASS THE PARSED JSON OBJECT TO IT
var fooJSON = new Foo(JSON.parse('{"a":4,"b":3}'));

alert(fooJSON.test() ); //Prints 12

আমি মনে করি আপনিও এর "বিপরীত" করতে পারেন। একটি ফাঁকা ফু অবজেক্ট তৈরি করুন এবং fooJSON থেকে নতুন ফু অবজেক্টে বৈশিষ্ট্যগুলি অনুলিপি করুন। অবশেষে, ফু অবজেক্টের দিকে নির্দেশ করতে fooJSON সেট করুন।
বিমিনিয়ার 18

8
এটি অত্যন্ত বিপজ্জনক। যদি আপত্তিটির এমন কোনও বৈশিষ্ট্য থাকে যা ফু সংজ্ঞায় নয়, আপনি একটি অতিরিক্ত লুকানো সম্পত্তি সহ একটি ফু অবজেক্ট তৈরি করবেন যা আপনি এর নাম জানেন না ... একটি লুপের পরিবর্তে আমি কেবল এটি করব: this.a = objজজ। a এবং this.b = obj.b. বা সরাসরি আমি "a" এবং "b" কে প্যারামিটার হিসাবে পাস করব: নতুন ফু (obj.a, obj.b)
গ্যাব্রিয়েল

2
গাগলকাসের পরামর্শটি শ্রবণযোগ্য। (যদিও "খুব বিপজ্জনক" সামান্য ওটিটি)) উপরে উদাহরণটি কেবল আপনাকে একটি ধারণা দেওয়ার জন্য। সঠিক প্রয়োগটি আপনার আবেদনের উপর নির্ভর করবে।
অলিভার মুরান

11
আপনি প্রোটোটাইপ বৈশিষ্ট্য থেকে নিজেকে রক্ষা করতে চাইতে পারেন। for (var prop in obj) {if (obj.hasOwnProperty(prop)) {this[prop] = obj[prop];}}
রোম্যান ভের্নোরি

3
@RomainVergnory জন্য আরও বেশি নিরাপত্তা, আমি শুধুমাত্র আরম্ভ কন্সট্রাকটর তৈরি সম্পত্তি, obj পরিবর্তে এই: for (var prop in obj) {if (this.hasOwnProperty(prop)) {this[prop] = obj[prop];}}। এই অনুমান আপনি সার্ভারে সব সম্পত্তি পূরণ করবে, আইএমও এছাড়াও নিক্ষেপ উচিত obj.hasOwnProperty () ব্যর্থ ...
tekHedd

42

আপনি কি জেএসএন সিরিয়ালাইজেশন / ডিসরিয়ালাইজেশন কার্যকারিতা যুক্ত করতে চান, তাই না? তারপরে এটি দেখুন:

আপনি এটি অর্জন করতে চান:

ইউএমএল

toJson () একটি সাধারণ পদ্ধতি।
fromJson () একটি স্থির পদ্ধতি।

বাস্তবায়ন :

var Book = function (title, author, isbn, price, stock){
    this.title = title;
    this.author = author;
    this.isbn = isbn;
    this.price = price;
    this.stock = stock;

    this.toJson = function (){
        return ("{" +
            "\"title\":\"" + this.title + "\"," +
            "\"author\":\"" + this.author + "\"," +
            "\"isbn\":\"" + this.isbn + "\"," +
            "\"price\":" + this.price + "," +
            "\"stock\":" + this.stock +
        "}");
    };
};

Book.fromJson = function (json){
    var obj = JSON.parse (json);
    return new Book (obj.title, obj.author, obj.isbn, obj.price, obj.stock);
};

ব্যবহার :

var book = new Book ("t", "a", "i", 10, 10);
var json = book.toJson ();
alert (json); //prints: {"title":"t","author":"a","isbn":"i","price":10,"stock":10}

var book = Book.fromJson (json);
alert (book.title); //prints: t

দ্রষ্টব্য: আপনি আপনার মত সব সম্পত্তি সংজ্ঞা পরিবর্তন করতে পারেন চান this.title, this.authorইত্যাদি দ্বারা var title, var authorইত্যাদি এবং তাদের getters যোগ ইউএমএল সংজ্ঞা সম্পন্ন করার জন্য।


4
আমি রাজী. এই বাস্তবায়ন অবশ্যই কাজ করবে, এবং এটি দুর্দান্ত ... বুক অবজেক্টের জন্য কেবলমাত্র কিছুটা স্পষ্ট এবং নির্দিষ্ট। আইএমএইচও, জেএসের শক্তি প্রোটোটাইপ এবং আপনি চাইলে কিছু অতিরিক্ত সম্পত্তি রাখার ক্ষমতা থেকে আসে। এটাই আমি বলছি '। আমি সত্যিই ওয়ান-লাইনারের সন্ধান করছিলাম: x .__ প্রোটো__ = এক্স.প্রোটোটাইপ; (যদিও এটি এখন ব্রাউজারের সাথে সামঞ্জস্যপূর্ণ নয়)
বিমিনিয়ার 3:51

4
আপনার toJson()পদ্ধতিটি - এটি স্বতন্ত্র বৈশিষ্ট্যগুলি হার্ডকডযুক্ত রয়েছে কিনা বা প্রত্যেকের জন্য একটি ব্যবহার করে তা নির্বিশেষে ভুলে যাবেন না - প্রতিটি স্ট্রিংয়ের সম্পত্তিতে থাকতে পারে এমন কয়েকটি অক্ষরের জন্য ব্যাকস্ল্যাশ এস্কেপ কোড যুক্ত করতে হবে। (উদাহরণস্বরূপ কোনও বইয়ের শিরোনামে উদ্ধৃতি চিহ্ন থাকতে পারে))
nnnnnn

1
হ্যাঁ, আমি জানি, আমার উত্তরটি একটি উদাহরণ এবং প্রশ্নের সেরা উত্তর ছিল, তবে ... এমনকি একটি ইতিবাচক বিষয়ও নয় ... আমি জানি না কেন আমি কেন অন্যদের সাহায্য করতে আমার সময় নষ্ট করি
গ্যাব্রিয়েল লালামাস

7
এই দিনগুলিতে আমি JSON.stringify()নিজে জেএসনকে () লেখার পরিবর্তে ব্যবহার করব। সমস্ত আধুনিক ব্রাউজার এটি সমর্থন করে এখন চাকাটি পুনরায় উদ্ভাবনের দরকার নেই।
পাথর

2
@ স্পাইপেকেকসের সাথে একমত আপনি যদি কেবলমাত্র বৈশিষ্ট্যের একটি উপসেটকে সিরিয়ালাইজ করতে চান তবে ক্রমিক বৈশিষ্ট্যগুলির ধ্রুবক তৈরি করুন। serializable = ['title', 'author', ...]JSON.stringify(serializable.reduce((obj, prop) => {...obj, [prop]: this[prop]}, {}))
অ্যাটিকাস

18

একটি ব্লগ পোস্ট যা আমি দরকারী বলে মনে করেছি: জাভাস্ক্রিপ্ট প্রোটোটাইপগুলি বোঝা

আপনি অবজেক্টের __ প্রোফাইল__ সম্পত্তি নিয়ে গণ্ডগোল করতে পারেন।

var fooJSON = jQuery.parseJSON({"a":4, "b": 3});
fooJSON.__proto__ = Foo.prototype;

এটি fooJSON কে ফু প্রোটোটাইপের উত্তরাধিকারী করার অনুমতি দেয়।

আমি মনে করি না এটি আইই তে কাজ করে, যদিও ... কমপক্ষে আমি যা পড়েছি তা থেকে।


2
আসলে, এরকম কিছু ছিল আমার প্রথম প্রবৃত্তি।
অলিভার মুরান

14
নোট যে __proto__দীর্ঘ অবচয় করা হয়েছে । তদুপরি, কার্য সম্পাদনের কারণে, ইতিমধ্যে তৈরি করা কোনও অবজেক্টের ([সেট করে __proto__বা অন্য কোনও উপায়ে) অভ্যন্তরীণ সম্পত্তি [[প্রোটোটাইপ]] সংশোধন করার প্রস্তাব দেওয়া হয় না ।
ইউ আসাকুসা

1
হায়, আসলে অবচয়হীন সমাধানগুলির
কোনওটিই এর

আমি পরিবর্তনের পারফরম্যান্সের কয়েকটি পরীক্ষা করেছি [[prototype]]এবং এটি ক্রোমে অপ্রাসঙ্গিক বলে মনে হচ্ছে। ফায়ারফক্সে নতুন কল করা প্রোটোটাইপ ব্যবহারের চেয়ে ধীর এবং অবজেক্ট.ক্রিয়েট সবচেয়ে দ্রুত। আমার ধারণা এফএফের সাথে ইস্যুটি হ'ল প্রথম পরীক্ষাটি শেষের চেয়ে ধীর, কেবলমাত্র মৃত্যুদন্ড কার্যকর করার বিষয়টি। ক্রোমে সমস্ত কিছু প্রায় একই গতিতে চলে। আমার অর্থ সম্পত্তি অ্যাক্সেস এবং পদ্ধতিগুলির এনভোকেশন। ক্রিয়েটিন নতুনের সাথে দ্রুত, তবে এটি এত গুরুত্বপূর্ণ নয়। দেখুন: jsperf.com/prototype-change-test-8874874/1 এবং: jsperf.com/prototype- পরিবর্তন- আদর্শবাদী
বোগদান মার্ট

4
আমি মনে করি আজকাল, কেউ Object.setPrototypeOf(fooJSON, Foo.prototype)সেটিংয়ের পরিবর্তে ফোন করবে fooJSON.__proto__... তাই না?
স্টাকেক্স -

11

আমি কি প্রশ্নে কিছু অনুপস্থিত বা অন্য কেউ কেন ২০১১ সাল থেকে reviverপ্যারামিটার উল্লেখ JSON.parseকরেনি?

সমাধানের জন্য এখানে সরল কোড রয়েছে যা: https://jsfiddle.net/Ldr2utrr/

function Foo()
{
   this.a = 3;
   this.b = 2;
   this.test = function() {return this.a*this.b;};
}


var fooObj = new Foo();
alert(fooObj.test() ); //Prints 6
var fooJSON = JSON.parse(`{"a":4, "b": 3}`, function(key,value){
if(key!=="") return value; //logic of course should be more complex for handling nested objects etc.
  let res = new Foo();
  res.a = value.a;
  res.b = value.b;
  return res;
});
// Here you already get Foo object back
alert(fooJSON.test() ); //Prints 12

পিএস: আপনার প্রশ্নটি বিভ্রান্তিকর: >> এটি দুর্দান্ত তবে আমি কীভাবে সেই জাভাস্ক্রিপ্ট অবজেক্টটি গ্রহণ করব এবং এটিকে একটি নির্দিষ্ট জাভাস্ক্রিপ্ট অবজেক্টে (যেমন একটি নির্দিষ্ট প্রোটোটাইপের সাহায্যে) রূপান্তর করতে পারি? শিরোনামের বিপরীতে, যেখানে আপনি জেএসএন পার্সিং সম্পর্কে জিজ্ঞাসা করেছেন তবে উদ্ধৃত অনুচ্ছেদটি জেএস রানটাইম অবজেক্ট প্রোটোটাইপ প্রতিস্থাপন সম্পর্কে জিজ্ঞাসা করে।


3

একটি বিকল্প পদ্ধতির ব্যবহার করা যেতে পারে Object.create। প্রথম যুক্তি হিসাবে, আপনি প্রোটোটাইপটি পাস করেন এবং দ্বিতীয়টির জন্য আপনি সম্পত্তি নামের একটি মানচিত্র বর্ণনাকারীদের কাছে প্রেরণ করেন:

function SomeConstructor() {
  
};

SomeConstructor.prototype = {
  doStuff: function() {
      console.log("Some stuff"); 
  }
};

var jsonText = '{ "text": "hello wrold" }';
var deserialized = JSON.parse(jsonText);

// This will build a property to descriptor map
// required for #2 argument of Object.create
var descriptors = Object.keys(deserialized)
  .reduce(function(result, property) {
    result[property] = Object.getOwnPropertyDescriptor(deserialized, property);
  }, {});

var obj = Object.create(SomeConstructor.prototype, descriptors);


3

আমি কনস্ট্রাক্টরকে একটি argumentচ্ছিক যুক্তি যুক্ত করা এবং কল করা পছন্দ করি Object.assign(this, obj), তারপরে যে কোনও বৈশিষ্ট্য যা বস্তু বা বস্তুর অ্যারে হয় সেগুলি হ্যান্ডেল করা:

constructor(obj) {
    if (obj != null) {
        Object.assign(this, obj);
        if (this.ingredients != null) {
            this.ingredients = this.ingredients.map(x => new Ingredient(x));
        }
    }
}

2

সম্পূর্ণতার জন্য, এখানে একটি সাধারণ ওয়ান-লাইনারটি আমি শেষ করে দিয়েছি (নন-ফু-প্রোপার্টিগুলির জন্য আমার কোনও পরীক্ষার দরকার নেই):

var Foo = function(){ this.bar = 1; };

// angular version
var foo = angular.extend(new Foo(), angular.fromJson('{ "bar" : 2 }'));

// jquery version
var foo = jQuery.extend(new Foo(), jQuery.parseJSON('{ "bar" : 3 }'));

2

আমি একটি প্যাকেজ তৈরি করেছি জাসন-ড্রাই । এটি (বিজ্ঞপ্তি) রেফারেন্স এবং শ্রেণীর উদাহরণগুলি সমর্থন করে supports

আপনাকে আপনার ক্লাসে 2 টি নতুন পদ্ধতি সংজ্ঞায়িত করতে হবে ( toDryপ্রোটোটাইপে এবং unDryএকটি স্ট্যাটিক পদ্ধতি হিসাবে), ক্লাসটি নিবন্ধ করুন ( Dry.registerClass), এবং আপনি যাচ্ছেন।


1

যদিও এটি প্রযুক্তিগতভাবে আপনি যা চান তা নয়, আপনি যদি জানেন যে আপনি কী ধরণের অবজেক্টটি পরিচালনা করতে চান তা আপনি নিজের পরিচিত বস্তুর প্রোটোটাইপের কল / প্রয়োগ পদ্ধতি ব্যবহার করতে পারেন।

আপনি এটি পরিবর্তন করতে পারেন

alert(fooJSON.test() ); //Prints 12

এই

alert(Foo.prototype.test.call(fooJSON); //Prints 12

1

আমি যে সমাধানগুলি সন্ধান করতে পেরেছিলাম এবং এগুলি একটি জেনেরিকের মধ্যে সংকলিত করেছি যা স্বয়ংক্রিয়ভাবে একটি কাস্টম অবজেক্ট এবং এর সমস্ত ক্ষেত্রগুলি পুনরাবৃত্তভাবে পার্স করতে পারে যাতে আপনি ডিসিরিয়ালেসনের পরে প্রোটোটাইপ পদ্ধতি ব্যবহার করতে পারেন।

একটি অনুমান হ'ল আপনি একটি বিশেষ ফাইল করা সংজ্ঞায়িত করেছেন যা এটি নির্দেশ করে যে প্রতিটি বস্তুর মধ্যে এটি টাইপ আপনি স্বয়ংক্রিয়ভাবে প্রয়োগ করতে চান ( this.__typeউদাহরণস্বরূপ)।

function Msg(data) {
    //... your init code
    this.data = data //can be another object or an array of objects of custom types. 
                     //If those objects defines `this.__type', their types will be assigned automatically as well
    this.__type = "Msg"; // <- store the object's type to assign it automatically
}

Msg.prototype = {
    createErrorMsg: function(errorMsg){
        return new Msg(0, null, errorMsg)
    },
    isSuccess: function(){
        return this.errorMsg == null;
    }
}

ব্যবহার:

var responseMsg = //json string of Msg object received;
responseMsg = assignType(responseMsg);

if(responseMsg.isSuccess()){ // isSuccess() is now available
      //furhter logic
      //...
}

টাইপ অ্যাসাইনমেন্ট ফাংশন (এটি কোনও নেস্টেড অবজেক্টগুলিকে টাইপ দেওয়ার জন্য পুনরাবৃত্তভাবে কাজ করে; এটি কোনও উপযুক্ত বস্তু সন্ধানের জন্য অ্যারের মাধ্যমে পুনরাবৃত্তি করে):

function assignType(object){
    if(object && typeof(object) === 'object' && window[object.__type]) {
        object = assignTypeRecursion(object.__type, object);
    }
    return object;
}

function assignTypeRecursion(type, object){
    for (var key in object) {
        if (object.hasOwnProperty(key)) {
            var obj = object[key];
            if(Array.isArray(obj)){
                 for(var i = 0; i < obj.length; ++i){
                     var arrItem = obj[i];
                     if(arrItem && typeof(arrItem) === 'object' && window[arrItem.__type]) {
                         obj[i] = assignTypeRecursion(arrItem.__type, arrItem);
                     }
                 }
            } else  if(obj && typeof(obj) === 'object' && window[obj.__type]) {
                object[key] = assignTypeRecursion(obj.__type, obj);
            }
        }
    }
    return Object.assign(new window[type](), object);
}

0

বর্তমানে গৃহীত উত্তরটি আমার পক্ষে কাজ করছে না। আপনাকে অবজেক্ট.সেসাইন () সঠিকভাবে ব্যবহার করতে হবে:

class Person {
    constructor(name, age){
        this.name = name;
        this.age = age;
    }

    greet(){
        return `hello my name is ${ this.name } and i am ${ this.age } years old`;
    }
}

আপনি সাধারণত এই শ্রেণীর অবজেক্ট তৈরি করেন:

let matt = new Person('matt', 12);
console.log(matt.greet()); // prints "hello my name is matt and i am 12 years old"

আপনার যদি জসন স্ট্রিং থাকে তবে আপনাকে ব্যক্তিগত শ্রেণিতে পার্স করতে হবে, এটি এর মতো করুন:

let str = '{"name": "john", "age": 15}';
let john = JSON.parse(str); // parses string into normal Object type

console.log(john.greet()); // error!!

john = Object.assign(Person.prototype, john); // now john is a Person type
console.log(john.greet()); // now this works

-3

জলপাইয়ের উত্তরগুলি খুব স্পষ্ট, তবে আপনি যদি কৌণিক জেএসে কোনও সমাধান খুঁজছেন তবে আমি একটি দুর্দান্ত মডিউল লিখেছি যার নাম কৌণিক-জেএসক্লাস যা এই স্বাচ্ছন্দ্য করে, লিটারাল নোটেশনে সংজ্ঞায়িত অবজেক্টগুলি সর্বদা খারাপ হয় যখন আপনি কোনও বড় প্রকল্পের দিকে লক্ষ্য রাখছেন কিন্তু এই বলে যে বিকাশকারীরা সমস্যার মুখোমুখি হন যা ঠিক বিএমইনার বলেছিল, কীভাবে জেসনকে প্রোটোটাইপ বা কনস্ট্রাক্টর স্বরলিপি অবজেক্টগুলিতে সিরিয়ালাইজ করা যায়

var jone = new Student();
jone.populate(jsonString); // populate Student class with Json string
console.log(jone.getName()); // Student Object is ready to use

https://github.com/imalhasaranga/Angular-JSClass

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