2009-06-03 8 views
49

की स्वचालित संपत्ति deserialization मुझे JSON में एक उचित सी # कक्षा में प्रतिनिधित्व की गई कुछ जावास्क्रिप्ट ऑब्जेक्ट को deserialize करने की आवश्यकता है। स्वचालित गुणों की अच्छी विशेषताओं को देखते हुए, मैं इन वर्गों में केवल फ़ील्ड होने के विरोध में उन्हें पसंद करना पसंद करूंगा। दुर्भाग्यवश, .NET serialization इंजन (कम से कम, डिफ़ॉल्ट रूप से) पूरी तरह से deserialization पर स्वचालित गुणों को अनदेखा करता है और केवल बैकिंग फ़ील्ड की परवाह करता है, जो स्पष्ट रूप से जावास्क्रिप्ट ऑब्जेक्ट में मौजूद नहीं है।सी # JSON

यह देखते हुए कि no standard way to name backing fields है और ईमानदार होने के लिए मैं "एक जावास्क्रिप्ट ऑब्जेक्ट बनाने की अनुमति देता हूं जो ऐसा लगता है कि इसमें सी # बैकिंग फ़ील्ड" दृष्टिकोण है क्योंकि यह थोड़ा गंदा लगता है, एकमात्र तरीका मैं कर सकता था सी # ऑटो-प्रॉपर्टीज में जावास्क्रिप्ट फ़ील्ड को क्रमबद्ध करें यदि मैं सीरियलाइजेशन इंजन को किसी भी तरह बैकिंग फ़ील्ड को अनदेखा कर सकता हूं और सीधे संपत्ति का उपयोग कर सकता हूं। दुर्भाग्य से, मैं यह नहीं समझ सकता कि यह कैसे किया जाता है या यदि यह बिल्कुल किया जा सकता है। किसी भी सुझाव की सराहना की जाएगी।

संपादित:

जावास्क्रिप्ट:

function Cat() 
{ 
    this.Name = "Whiskers"; 
    this.Breed = "Tabby"; 
} 
var cat = new Cat(); 

यह तो करने के लिए धारावाहिक है "{नाम: 'व्हिस्कर्स'}" यहाँ एक उदाहरण है।

सी # वर्ग:

[Serializable()] 
public class Cat 
{ 
    public string Name { get; set; } 
    public string Breed { get; set; } 
} 

और अक्रमांकन कोड, यह काम नहीं करता:

new DataContractJsonSerializer(typeof(Cat)).ReadObject(inputStream); 

और यह अपवाद से स्पष्ट है कि यह विफल रहता है, क्योंकि यह समर्थन क्षेत्र के लिए लग रही है।

EDIT2: यहाँ अपवाद है, कि अगर मदद करता है (कोई आंतरिक अपवाद):

System.Runtime.Serialization.SerializationException

"डेटा अनुबंध प्रकार 'Test.Cat' नहीं कर सकते deserialized हो क्योंकि आवश्यक डेटा सदस्यों '<Name>k__BackingField, <Breed>k__BackingField' नहीं मिला। "

+0

क्या आप इसका मतलब बता सकते हैं कि आपका क्या मतलब है? –

+0

@ जॉन सॉंडर्स - मान लें कि मुझे "बिल्ली" नामक एक जावास्क्रिप्ट ऑब्जेक्ट मिला है जिसे "नाम" नामक एक फ़ील्ड "व्हिस्कर्स" के साथ कहा जाता है। मान लें कि यह JSON में दर्शाया गया है। मैं इस जेएसओएन को पकड़ना चाहता हूं और सी # बिल्ली वर्ग (मेरे द्वारा लिखित) के उदाहरण के लिए इसे क्रमबद्ध करना चाहता हूं ताकि धारावाहिक प्रक्रिया "व्हिस्कर्स" के साथ उदाहरण के स्वचालित गुण "नाम" को पॉप्युलेट कर दे। –

+0

... लेकिन समस्या यह है कि धारावाहिक बैकिंग फ़ील्ड की तलाश में है (उदाहरण के लिए " k_backingField" लेकिन इस नाम के साथ जरूरी नहीं है ") और नहीं" नाम "। –

उत्तर

79

यहां क्या हो रहा है deserializer आपके बैकिंग फ़ील्ड के नाम का अनुमान लगाने का प्रयास कर रहा है। आप (DataContract/DataMember जिम्मेदार बताते हैं) इस तरह स्पष्ट मैपिंग जोड़कर इस का समाधान कर सकते हैं:

[DataContract] 
public class Cat 
{ 
    [DataMember] 
    public string Name { get; set; } 

    [DataMember] 
    public string Breed { get; set; } 
} 
+0

+1 पहला प्रश्न मैंने उत्तर दिया, लेकिन मेरे पास उस समय उत्तर देने का प्रतिनिधि नहीं था! – amelvin

+2

अगर मैं कर सकता तो मैं +2 चाहता। थोड़ी देर के लिए इसका उत्तर खोज रहे हैं। – Kelly

+0

सुपर! मैंने [DataContract] विशेषता को याद किया :( – Ruutert

20

आप JavaScriptSerializerSystem.Web.Script.Serialization नाम स्थान में पाया के साथ ऐसा कर सकते हैं:

JavaScriptSerializer serializer = new JavaScriptSerializer(); 
Cat c = serializer.Deserialize<Cat>(jsonString); 

मैं POCO स्वत: गुणों के साथ वस्तुओं और यह सिर्फ ठीक काम करता है है।

संपादित करें: मैंने JSON Serializers in .NET लिखा है जो DataContractJsonSerializer के साथ इस धारावाहिक की तुलना करता है।

+0

हाँ ऐसा लगता है कि मैं अच्छे पुराने जेसनएक्ससेरियलाइज़र के साथ फंस जाऊंगा http://code.google.com/p/ jsonexserializer/ –

1

मुझे लगता है कि आप एक वेब सेवा के माध्यम से डेटा पास कर रहे हैं। यदि आप WebService क्लास का उपयोग स्क्रिप्ट विधि विधि के साथ अनियमित आउट के साथ कर रहे हैं, तो वेब सेवा विधियां JSON को मूल रूप से पढ़ सकती हैं। वे ऊपर वर्णित एक ही जावास्क्रिप्टसेरियलाइज़र का भी उपयोग करते हैं। यदि आप डब्ल्यूसीएफ का उपयोग कर रहे हैं तो मैं तर्क पर थोड़ा और अस्पष्ट हूं।

लेकिन सुनिश्चित करें कि आपका JSON ऑब्जेक्ट आपकी कक्षा में प्रत्येक संपत्ति के लिए डेटा लौटा रहा है। आपकी त्रुटि में, एक नस्ल संपत्ति का उल्लेख है जो आपके उदाहरण में नहीं है।

इसके अलावा, जावास्क्रिप्ट पक्ष पर, जावास्क्रिप्ट की गतिशील प्रकृति के साथ करें, अपनी वस्तुओं में नई गुणों को जोड़ना आसान है। यह कभी-कभी परिपत्र संदर्भों का कारण बन सकता है। आपको जो भी अतिरिक्त डेटा जोड़ा जा सकता है उसे हटा देना चाहिए (जैसे आप वेब विधि के माध्यम से डेटा भेज रहे हैं, फिर एक बार पूरा होने के बाद इसे फिर से जोड़ें)।

+0

नहीं, दुर्भाग्यवश यह एक webservice नहीं है। यह एक साधारण AJAX अनुरोध है जो सर्वर पर जेसन में डेटा पास करता है। इसके अलावा, मुझे पूरा यकीन है कि कोई परिपत्र संदर्भ नहीं हैं। आप सही हैं कि उदाहरण में कोई नस्ल संपत्ति नहीं है लेकिन मेरे असली कोड में सभी गुण हैं। हालांकि सुझावों के लिए धन्यवाद :) –

+0

चीजों के जावास्क्रिप्ट पक्ष पर: आप जावास्क्रिप्ट ऑब्जेक्ट को JSON में कैसे परिवर्तित कर रहे हैं? –

+0

@ क्रिस ब्रांस्मा: सामान्य तरीका, json2.js के साथ: http://www.json.org/json2.js –

5

baretta's answer हल k__BackingField मेरे लिए ब्लोट। सिर्फ एक छोटे से परिशिष्ट कि आप ऑटो के लिए इस वर्ग को सजाने कर सकते हैं या तो XML या एक समान तरीके से JSON में क्रमानुसार:

[Serializable, XmlRoot, DataContract] 
public class Cat 
{ 
    [XmlElement] 
    [DataMember] 
    public string Name { get; set; } 
    [XmlElement] 
    [DataMember] 
    public string Breed { get; set; } 
} 

... और फिर एक DataContractJsonSerializer या XmlSerializer का उपयोग अपने endpoint के लिए तैयार है।