2015-04-17 7 views
15

मैं टाइपप्रति उपयोग कर रहा हूँ कुछ वर्गों को परिभाषित करने के लिए और जब मैं एक संपत्ति बनाने के लिए, यह निम्नलिखित plunkr में Class1 के बराबर उत्पन्न करता है:Object.defineProperty serializing से JSON.stringify से बचाता है यह

http://plnkr.co/edit/NXUo7zjJZaUuyv54TD9i?p=preview

var Class1 = function() { 
    this._name = "test1"; 
} 

Object.defineProperty(Class1.prototype, "Name", { 
    get: function() { return this._name; }, 
    set: function(value) { this._name = value; }, 
    enumerable: true 
}); 

JSON.stringify(new Class1()); // Will be "{"_name":"test1"}" 

जब serializing, यह उस संपत्ति को आउटपुट नहीं करता है जिसे मैंने अभी परिभाषित किया है।

instance2 और instance3 व्यवहार करते हैं क्योंकि मैं परिभाषित संपत्ति को क्रमबद्ध करके अपेक्षा करता हूं। (प्लंकर आउटपुट देखें)।

मेरा वास्तविक प्रश्न है: क्या यह सामान्य है?

यदि हां, तो मैं सबसे कुशल तरीके से इसके आसपास कैसे काम करूं?

उत्तर

16

आप अपने प्रोटोटाइप पर toJSON() विधि को परिभाषित करने के तरीके को कस्टमाइज़ करने के तरीके को अनुकूलित करने के लिए परिभाषित कर सकते हैं।

Class1.prototype.toJSON = function() { 
    return { 
     Name: this.Name 
    }; 
}; 
JSON.stringify(new Class1()); // Will be '{"Name":"test1"}' 
+1

मैं इसे उत्तर के रूप में चिह्नित कर रहा हूं क्योंकि मैं स्वयं जेसन को कार्यान्वित कर रहा हूं। मेरे पास सार्वजनिक संपत्तियों के लिए पहले से ही निजी सदस्यों का नक्शा था क्योंकि मैं इसे अपने एपीआई से कुछ टाइपऑन क्लास में कुछ JSON मैप करने के लिए उपयोग कर रहा था। टूजेसन विधियों में, मैं उलटा नामों के साथ सभी गुणों के साथ एक नई वस्तु बनाने के लिए बस उस मानचित्र का उपयोग करता हूं। मैं जल्द ही इसके बारे में ब्लॉग करूंगा। –

1

जैसा कि आपने पाया है, यह प्रोटोटाइप पर परिभाषित गुणों को क्रमबद्ध नहीं करेगा।

मैं जानता हूँ कि यह आदर्श नहीं है, लेकिन एक और विकल्प यह करने के लिए है:

class Class1 { 
    private _name = "test1"; 

    Name: string; // do this to make the compiler happy 

    constructor() { 
     Object.defineProperty(this, "Name", { 
      get: function() { return this._name; }, 
      set: function(value) { this._name = value; }, 
      enumerable: true 
     }); 
    } 
} 

उदाहरण पर संपत्ति की परिभाषा संपत्ति को क्रमानुसार होगा।

+0

मैंने इसे माना था, लेकिन मुझे एक समाधान चाहिए जो टाइपस्क्रिप्ट का उपयोग करता है। –

+2

@ क्रिस्टियन ड्राउल्स हाँ, मैं इस समाधान का उपयोग नहीं करता:) ... एक toJSON विधि जोड़ना एक बेहतर विकल्प है। –

7

हां, यह डिज़ाइन द्वारा है।

रूप ECMA में परिभाषित किया गया है, केवल खुद गणनीय गुण क्रमांकित हैं (stringify() अन्य लोगों के अलावा, Object.keys() के संदर्भ में परिभाषित किया गया है)।

संपत्ति एक्सेसर्स टाइपस्क्रिप्ट और ES6 दोनों में प्रोटोटाइप पर परिभाषित किए जाते हैं।

और अपने अंतिम प्रश्न का उत्तर देते हुए, यह ऑपरेशन करने के लिए सबसे अधिक सुविधाजनक तरीका है।

इसके अलावा, केवल एक) serialization के प्रत्येक ऑब्जेक्ट भाग में एक toJSON() को परिभाषित करता है, या बी) JSON.stringify() पर दूसरे तर्क के रूप में एक replacer फ़ंक्शन/सरणी को पारित करता है।

प्रोटोटाइप से श्वेतसूची प्रॉपर्टीज़:

JSON.stringify(instance, Object.keys(instance.constructor.prototype)) 
+0

मैं toJSON दृष्टिकोण के साथ गया था। मैं जल्द ही इसके बारे में ब्लॉग करूंगा। –

15

आप इसे आगे बढ़ाने के लिए पसंद करते हैं, टाइपप्रति के लिए सज्जाकार प्रस्ताव को आजमाइए:

इस प्रस्ताव के अनुसार (https://github.com/wycats/javascript-decorators):

एक सजावटी है:

  • एक अभिव्यक्ति
  • कि एक समारोह
  • कि लक्ष्य, नाम लेता है, और संपत्ति वर्णनकर्ता का मूल्यांकन के रूप में तर्क
  • और वैकल्पिक रूप से एक संपत्ति वर्णनकर्ता रिटर्न लक्ष्य वस्तु

यह इस तरह से चला जाता है पर स्थापित करने के लिए (उच्च स्तर देखें):

क्लाइंट कोड:

@serializable() 
class Person { 

    constructor(name: string) { 
     this._name = name; 
    } 

    private _name: string; 

    @serialize() 
    get name() { 
     return this._name; 
    } 

    @serialize('Language') 
    get lang() { 
     return 'JavaScript'; 
    } 
} 

इन्फ्रास्ट्रक्चर:

const serialized = new WeakMap(); 

export function serializable(name?: string) { 
    return function (target, propertyKey, descriptor) { 
     target.prototype.toJSON = function() { 
      const map = serialized.get(target.prototype); 
      const props = Object.keys(map); 
      return props.reduce((previous, key) => { 
       previous[map[key]] = this[key]; 
       return previous; 
      }, {}); 
     } 

    } 
} 

export function serialize(name?: string) { 
    return function (target, propertyKey, descriptor) { 
     let map = serialized.get(target); 
     if (!map) { 
      map = {}; 
      serialized.set(target, map); 
     } 

     map[propertyKey] = name || propertyKey; 
    } 
} 

अद्यतन: मैं एक भंडार में इस नमूने डेकोरेटर https://github.com/awerlang/es-decorators

+0

बहुत रोचक! लेकिन इस परियोजना के लिए अल्प अवधि में व्यवहार्य समाधान नहीं है। धन्यवाद! –

+0

हां, आप सही हैं, लेकिन मुझे यह बहुत ही आशाजनक लगता है और इसे जल्द ही उत्पादन में उपयोग करने की उम्मीद है –

+0

मुझे पता है कि टाइपस्क्रिप्ट को अद्यतन करने के बाद से यह पूछने में थोड़ा देर हो चुकी है, लेकिन मेरे मामले में, वीकैप हमेशा खाली रहता है 'serialize' कहा जाता है। कोई उपाय ? – Jacks

1

पर कुछ यहां कुछ लिखें उम्मीद है कि निकाले दूसरों की मदद कर सकते हैं। मैं ठीक लिए क्या

var newObject = $.extend(false, {}, orginalObj); 

तो प्रोटोटाइप पर परिभाषित गुण मैं newObject नोटिस प्रोटोटाइप गुण के बजाय उदाहरण के गुण होते हैं क्रमानुसार नहीं JSON.stringify है क्या। मैं टाइपस्क्रिप्ट का उपयोग कर रहा हूं और एक्सेसर प्राप्त कर रहा हूं।

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