2012-12-25 10 views
9

eval या JSON.parse का उपयोग कर जावास्क्रिप्ट में किसी ऑब्जेक्ट में जेएसओएन लोड करना आसान है।JSON से मूल ऑब्जेक्ट/प्रकार को पुनर्स्थापित कैसे करें?

लेकिन यदि आपके पास उचित "वर्ग" फ़ंक्शन जैसा है, तो आप इसमें JSON डेटा कैसे प्राप्त करते हैं?

उदा।

function Person(name) { 
    this.name=name; 
    this.address = new Array(); 
    this.friendList; 

    this.promote = function(){ 
    // do some complex stuff 
    } 
    this.addAddress = function(address) { 
    this.address.push(address) 
    } 
} 

var aPersonJSON = '{\"name\":\"Bob\",\"address\":[{\"street\":\"good st\",\"postcode\":\"ADSF\"}]}' 

var aPerson = eval("(" + aPersonJSON + ")"); // or JSON.parse 
//alert (aPerson.name); // Bob 
var someAddress = {street:"bad st",postcode:"HELL"}; 
//alert (someAddress.street); // bad st 
aPerson.addAddress(someAddress); // fail! 

जड़ मैं JSON से उचित व्यक्ति उदाहरण बना करने में सक्षम होने की जरूरत है है, लेकिन सभी मैं प्राप्त कर सकते हैं एक गूंगा वस्तु है। मैं सोच रहा हूं कि प्रोटोटाइप के साथ कुछ करना संभव है?

मैं JSON की प्रत्येक पंक्ति को पार्स नहीं करना चाहता हूं और प्रत्येक चर को अनुरूप कार्यों के गुणों में असाइन करना चाहता हूं, जो बहुत मुश्किल होगा। मेरे पास वास्तविक जेएसओएन और फ़ंक्शंस ऊपर दिए गए उदाहरण से कहीं अधिक जटिल हैं।

मुझे लगता है कि कोई JSON स्ट्रिंग में फ़ंक्शन विधियों को JSONify कर सकता है, लेकिन जैसा कि मुझे परिणामस्वरूप डेटा को जितना संभव हो सके छोटा रखना है, यह एक विकल्प नहीं है - मैं केवल डेटा को स्टोर और लोड करना चाहता हूं, जावास्क्रिप्ट नहीं तरीकों के लिए कोड।

मैं जेएसओएन द्वारा एक उप ऑब्जेक्ट के रूप में लोड डेटा को भी नहीं रखना चाहता हूं अगर मैं इसकी मदद कर सकता हूं (लेकिन एकमात्र तरीका हो सकता है), उदा।

function Person(name) { 
    this.data = {}; 
    this.data.name=name; 
} 

var newPerson = new Person(""); 
newPerson.data = eval("(" + aPersonJSON + ")"); 
alert (newPerson.data.name); // Bob 

कोई विचार?

+2

कृपया जेएसओएन को पार्स करने के लिए ['JSON.parse'] (http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/) का उपयोग करें और' eval' का उपयोग न करें। यदि लक्ष्य ब्राउज़र 'JSON.parse' (यानी आईई 7 या पुराना है) का समर्थन नहीं करते हैं, तो क्रॉकफ़ोर्ड के' json.js' के माध्यम से एक झुकाव (जो आंतरिक रूप से 'eval' का उपयोग करता है लेकिन सैनिटी सत्यापन भी प्रदान करता है) या' json2। जेएस 'आसानी से उपलब्ध है। –

+0

हाय, समस्या eval या parse नहीं है, जो दोनों एक ही untyped वस्तु उत्पन्न करते हैं, मैं जेएसओएन व्यक्ति फक्शन में पाने के लिए एक रास्ता खोजने की कोशिश कर रहा हूँ। इस पर कोई विचार? –

+0

@ जॉन लिटल कभी भी eval का उपयोग नहीं करते हैं, यह कई सुरक्षा मुद्दों (कोड इंजेक्शन इत्यादि) का स्रोत है [इसे पढ़ें] (http://stackoverflow.com/questions/197769/when-is-javascripts-eval-not-evil) – thepoosh

उत्तर

2

अपनी स्ट्रिंग को पार्स करने के लिए JSON.parse का उपयोग करने का सबसे आसान तरीका है, फिर ऑब्जेक्ट को फ़ंक्शन पर पास करें। JSON.parse ऑनलाइन json2 लाइब्रेरी का हिस्सा है।

+1

आधुनिक ब्राउज़र में JSON विधियां उपलब्ध हैं ... पुराने ब्राउज़र के लिए फ़ॉलबैक के रूप में लाइब्रेरी का उपयोग करें – charlietfl

+0

'JSON.stringify()' फ़ंक्शन ** नहीं है * पार्सिंग * के लिए **; यह ऑब्जेक्ट * को * JSON स्ट्रिंग में बदलने के लिए है। – Pointy

+0

हाय, यह क्रूक्स है, परिणामी जटिल ऑब्जेक्ट को कैसे फोकस करना है? आप इसे पास नहीं कर सकते - जब तक कि मैंने वस्तु को पार करने के लिए कुछ जटिल नहीं लिखा, प्रत्येक उप-ऑब्जेक्ट और डेटा आइटम को व्यक्ति objeject में कॉपी करना जो मैं नहीं करना चाहता, खासकर जब यह अक्सर बदलता है। –

8

कई ढांचे एक 'विस्तार' फ़ंक्शन प्रदान करते हैं जो फ़ील्ड को एक ऑब्जेक्ट से दूसरे ऑब्जेक्ट में कॉपी करेगा। आप जो चाहते हैं उसे करने के लिए आप JSON.parse के साथ इसे जोड़ सकते हैं।

newPerson = new Person(); 
_.extend(newPerson, JSON.parse(aPersonJSON)); 

आप कुछ की तरह शामिल करने के लिए नहीं करना चाहते हैं को रेखांकित आप हमेशा से ही समारोह का विस्तार या अपने खुद के बारे में कॉपी कर सकते हैं।

Coffeescript उदाहरण क्योंकि मैं ऊब गया था:

JSONExtend = (obj, json) -> 
    obj[field] = value for own field, value of JSON.parse json 
    return obj 

class Person 
    toString: -> "Hi I'm #{@name} and I'm #{@age} years old." 


dude = JSONExtend new Person, '{"name":"bob", "age":27}' 
console.log dude.toString() 
+0

विविध क्रोध करने के जोखिम पर, कॉफ़ीस्क्रिप्ट के लिए +1! –

0

मैं, न बहुत ज्यादा इस में है, लेकिन aPerson.addAddress काम नहीं करना चाहिए, क्यों वस्तु में सीधे बताए नहीं हूँ?

aPerson.address.push(someAddress); 
alert(aPerson.address); // alert [object object] 
16

आप एक reviver समारोह उपयोग करने की आवश्यकता: बस मामला किसी को जरूरत में

// Registry of types 
var Types = {}; 

function MyClass(foo, bar) { 
    this._foo = foo; 
    this._bar = bar; 
} 
Types.MyClass = MyClass; 

MyClass.prototype.getFoo = function() { 
    return this._foo; 
} 

// Method which will provide a JSON.stringifiable object 
MyClass.prototype.toJSON = function() { 
    return { 
    __type: 'MyClass', 
    foo: this._foo, 
    bar: this._bar 
    }; 
}; 

// Method that can deserialize JSON into an instance 
MyClass.revive = function(data) { 
    // TODO: do basic validation 
    return new MyClass(data.foo, data.bar); 
}; 

var instance = new MyClass('blah', 'blah'); 

// JSON obtained by stringifying an instance 
var json = JSON.stringify(instance); // "{"__type":"MyClass","foo":"blah","bar":"blah"}"; 

var obj = JSON.parse(json, function(key, value) { 
    return key === '' && value.hasOwnProperty('__type') 
    ? Types[value.__type].revive(value) 
    : this[key]; 
}); 

obj.getFoo(); // blah 

कोई अन्य वास्तव में जिस तरह से ...

+1

क्या इस समारोह को 'रिवाइवर' कहने के लिए कोई सम्मेलन है? – Bergi

+1

JSON ऑब्जेक्ट के लिए spec में, विधि (और औपचारिक तर्क) को पुनरावर्तक के रूप में संदर्भित किया जाता है। –

1

, यहाँ यह एक शुद्ध जावास्क्रिप्ट समारोह का विस्तार है (स्पष्ट रूप से एक वस्तु परिभाषा में होगा)।

this.extend = function (jsonString){ 
    var obj = JSON.parse(jsonString) 
    for (var key in obj) { 
     this[key] = obj[key] 
     console.log("Set ", key ," to ", obj[key]) 
     } 
    } 

कृपया console.log दूर करने के लिए मत भूलना: पार्टी के लिए देर से पी

1

एक छोटी सी, लेकिन यह किसी की मदद कर सकते हैं। यह कैसे मैं इसका समाधान कर लिया है, ES6 वाक्य रचना:

class Page 
{ 
    constructor() { 
     this.__className = "Page"; 
    } 

    __initialize() { 
     // Do whatever initialization you need here. 
     // We'll use this as a makeshift constructor. 
     // This method is NOT required, though 
    } 
} 

class PageSection 
{ 
    constructor() { 
     this.__className = "PageSection"; 
    } 
} 

class ObjectRebuilder 
{ 
    // We need this so we can instantiate objects from class name strings 
    static classList() { 
     return { 
      Page: Page, 
      PageSection: PageSection 
     } 
    } 

    // Checks if passed variable is object. 
    // Returns true for arrays as well, as intended 
    static isObject(varOrObj) { 
     return varOrObj !== null && typeof varOrObj === 'object'; 
    } 

    static restoreObject(obj) { 
     let newObj = obj; 

     // At this point we have regular javascript object 
     // which we got from JSON.parse. First, check if it 
     // has "__className" property which we defined in the 
     // constructor of each class 
     if (obj.hasOwnProperty("__className")) { 
      let list = ObjectRebuilder.classList(); 

      // Instantiate object of the correct class 
      newObj = new (list[obj["__className"]]); 

      // Copy all of current object's properties 
      // to the newly instantiated object 
      newObj = Object.assign(newObj, obj); 

      // Run the makeshift constructor, if the 
      // new object has one 
      if (newObj.__initialize === 'function') { 
       newObj.__initialize(); 
      } 
     } 

     // Iterate over all of the properties of the new 
     // object, and if some of them are objects (or arrays!) 
     // constructed by JSON.parse, run them through ObjectRebuilder 
     for (let prop of Object.keys(newObj)) { 
      if (ObjectRebuilder.isObject(newObj[prop])) { 
       newObj[prop] = ObjectRebuilder.restoreObject(newObj[prop]); 
      } 
     } 

     return newObj; 
    } 
} 

let page = new Page(); 
let section1 = new PageSection(); 
let section2 = new PageSection(); 

page.pageSections = [section1, section2]; 

let jsonString = JSON.stringify(page); 
let restoredPageWithPageSections = ObjectRebuilder.restoreObject(JSON.parse(jsonString)); 

console.log(restoredPageWithPageSections); 

आपका पेज, वर्ग Page की वस्तु के रूप में बहाल किया जाना चाहिए सरणी वर्ग PageSection के 2 वस्तुओं से युक्त के साथ। गहराई की परवाह किए बिना अंतिम वस्तु के लिए रिकर्सन सभी तरह से काम करता है।

@ सेन किन्से के जवाब ने मुझे अपने समाधान में मदद की।

संबंधित मुद्दे