15

मेरे पास एक ऑब्जेक्ट पेड़ है जिसे मैं JSON से DataContractJsonSerializer के साथ क्रमबद्ध कर रहा हूं। Dictionary<TKey, TValue> धारावाहिक हो जाता है, लेकिन मैं मार्कअप पसंद नहीं है - आइटम इस तरह गाया नहीं कर रहे हैं:सीरियलाइज डिक्शनरी <टीके, टीवीएयू> जेएसओएन से डेटाकंट्रैक्टजसन एसरियलाइज़र

{key1:value, key2:value2} 

बल्कि धारावाहिक KeyValuePair<TKey, TValue> ऑब्जेक्ट की श्रृंखला की तरह:

[{ 
    "__type":"KeyValuePairOfstringanyType:#System.Collections.Generic", 
    "key":"key1", 
    "value":"value1" 
},  
{ 
    "__type":"KeyValuePairOfstringanyType:#System.Collections.Generic", 
    "key":"key2", 
    "value":"value2" 
}] 

बदसूरत, ऐसा नहीं है ?

तो, मैं ISerializable लागू करता है जो सामान्य ऑब्जेक्ट में जेनेरिक डिक्शनरी को लपेटकर इसे से बचता हूं, और मैं GetObjectData विधि में अपने कस्टम क्रमबद्धता को लागू करता हूं (और इसमें केवल 3 लाइनें होती हैं)।

अब समस्या - मैं अपने वर्ग Dictionary<TKey, TValue> से निकाले जाते हैं नहीं कर सकते, तो मैं एक निजी Dictionary<TKey, TValue> क्षेत्र के लिए लागू किया जा रहा अपने कस्टम कक्षा में सभी तर्क (Add, Clear, आदि) को लागू करने,। विरासत बेहतर होगा क्योंकि मेरे कस्टम ऑब्जेक्ट का उपयोग करते समय मेरे पास मेरे सामान्य निपटान में सभी सामान्य शब्दकोश कार्यक्षमता होगी।

विरासत के साथ समस्या यह है कि

Dictionary<TKey, TValue> लागू करता है अपने आप ही ISerializable है, और DataContractJsonSerializer इस तरह भले ही मैं अपने कस्टम वर्ग से स्पष्ट रूप से ISerializable लागू इस कार्यान्वयन को पसंद करते हैं, लगता है:

public class MyClass : Dictionary<string, object>, ISerializable 
{ 
    public override void GetObjectData(SerializationInfo info, 
     StreamingContext context) 
} 

मैं वास्तव में हैरान था कि यह संभव है क्योंकि यह स्पष्ट रूप से स्पष्ट इंटरफ़ेस कार्यान्वयन का उपयोग करने में सक्षम होने के बिना दो बार एक ही इंटरफ़ेस को कार्यान्वित करने की अनुमति देता है - इसलिए मैंने ब्लॉग पोस्ट about multiple interface implementation

में स्थिति में अधिक विस्तार से स्थिति का विश्लेषण किया, तो, प्रयोगों मैं वहाँ किया के अनुसार, serializer ISerializable की मेरी कार्यान्वयन बुला होना चाहिए, कोई फर्क नहीं पड़ता कास्टिंग किस प्रकार आंतरिक रूप से प्रयोग किया जाता है -

((ISerializable)((Dictionary<,>)obj)).GetObjectData(...) 

या:

((ISerializable)obj).GetObjectData(...) 

लेकिन यह जाहिरा तौर पर नहीं है जैसा कि मैं परिणामस्वरूप जेएसओएन में देखता हूं कि KeyValuePair<TKey, TValue> धारावाहिक अभी भी कहा जा रहा है। क्या हो रहा है कि मैं याद कर रहा हूँ?

अद्यतन: उत्तर और टिप्पणियां जो मैं अब तक प्राप्त कर रहा हूं, वे केवल कामकाज का सुझाव दे रहे हैं।मैं उल्लेख किया है, तथापि, कि मैं एक समाधान है कि इस सवाल पूछने के साथ बहुत अच्छी तरह से काम करता है तो मैं 2 लक्ष्य हैं:

  1. अंततः यह मूल डिजाइन के साथ काम करने के - और मैं क्रमबद्धता तर्क को बदलने के लिए नहीं जा रहा हूँ इसके लिए, इस पर बहुत सारे कोड और तर्क निर्भर हैं

  2. मेरे सीरियलाइजेशन कोड का उपयोग करके DataContractJsonSerializer क्यों नहीं है, इस रहस्य को अनदेखा करने के लिए - जैसा कि मैंने ब्लॉग पोस्ट में देखा है, मैंने बनाया है इंटरफ़ेस कार्यान्वयन और विरासत के साथ सभी प्रकार के प्रयोगों और मुझे विश्वास था कि मैं प्रक्रिया के सभी इंस और आउट को समझ रहा हूं, इसलिए मैं समझने में असफल रहा हूं कि इसमें क्या हो रहा है केस

+1

ऐसा लगता है: विरासत के बारे में चिंता करने की जरूरत नहीं है। एक शब्दकोश से प्राप्त करने की कोशिश करने से बहुत कम काम। –

+0

आप 'JavaScriptSerializer' का भी उपयोग कर सकते हैं क्योंकि यह आपके द्वारा पसंद किए जाने वाले शब्दकोशों को क्रमबद्ध करता है। –

+0

@RitchMelton - शब्दकोश से विरासत में बहुत काम नहीं है, लेकिन मुझे यह स्वीकार करना होगा कि आईनेमरेबल को कार्यान्वित करना और सदस्य की शब्दकोश को वापस करना, पहली नजर में प्राप्त करना मेरे कामकाज से बेहतर प्रतीत होता है - – Vroomfundel

उत्तर

1

डेटाकंट्रैक्टजसनसेरियलाइज़र को अनुकूलित करने के लिए there is no way लगता है।

यदि आप अभी भी जो चाहते हैं उसे प्राप्त करना चाहते हैं, तो Json.Net का उपयोग करने पर विचार करें। यह DataContractJsonSerializer की तुलना में तेज़ और अधिक लचीला है। Json.Net की जेसन कनवर्टर अवधारणा को देखें। यह आपको क्रमबद्धता/deserialization प्रक्रिया को अनुकूलित करने की संभावना देता है।

इसके अलावा शब्दकोश क्रमबद्धरण का डिफ़ॉल्ट कार्यान्वयन सटीक है क्योंकि आप http://james.newtonking.com/projects/json/help/SerializingCollections.html चाहते हैं।

public Message <methodname> { 
    ... 
    string jsonMessage = JsonConvert.SerializeObject(myObjectTree); 
    return WebOperationContext.Current.CreateTextResponse(jsonMessage, "application/javascript; charset=utf-8", Encoding.UTF8); 
} 
+1

काम नहीं कर रही है। दान रिग्सबी द्वारा लिंक्ड आलेख में उल्लेख किया गया है कि डेटाकंट्रैक्टसेरियलाइज़र कॉन्फ़िगर करने योग्य नहीं है लेकिन यह स्पष्ट रूप से GetObjectData कार्यान्वयन क्यों नहीं कहा जा रहा है, इसकी खोज में लम्बाई के पास कहीं भी नहीं जाता है। इसके अलावा, मैं json.net अच्छी तरह से जानता हूं, और मुझे पता है कि यह अच्छा है - प्रोजेक्ट में सीरियलाइजेशन इंजन को बदलना बहुत बड़ा असर होगा - यह सिर्फ मेरा कस्टम डिक्शनरी नहीं है जिसे – Vroomfundel

+0

क्रमबद्ध किया जा रहा है रिग्सबी लिंक अब मर चुका है (DNS विफलता)। सभी मानक क्रमिकरण अनुकूलन तंत्र उपलब्ध हैं, क्योंकि यह सब 'XmlObjectSerializer' पर आधारित है। दुर्भाग्यवश, यह टैप करने के लिए "सरल" नहीं है (देखें "सरोगेट संपत्ति" उत्तर), लेकिन "कोई रास्ता नहीं" से दूर। –

0

@Pashec उल्लेख किया है, अगर आप Json.NET उपयोग करते हैं, तो आपको निम्न कोशिश कर सकते हैं जैसे आप एक IEnumerable वर्ग और अपने ISerializable implentation साथ शब्दकोश लपेट सकता है

public Dictionary<string, string> NodeData { get; set; } 

[DataMember(Name="NodeData")] 
private CustomDictionarySerializer NodeDataSurrogate 
{ 
    get 
    { 
     return new CustomDictionarySerializer(NodeData); 
    } 
    set 
    { 
     NodeData = value._data; 
    } 
} 

[Serializable] 
private class CustomDictionarySerializer : ISerializable 
{ 
    public Dictionary<string, string> _data; 

    public CustomDictionarySerializer(Dictionary<string, string> dict) 
    { 
     _data = dict; 
    } 

    public CustomDictionarySerializer(SerializationInfo info, StreamingContext context) 
    { 
     _data = new Dictionary<string, string>(); 
     var valueEnum = info.GetEnumerator(); 
     while(valueEnum.MoveNext()) 
     { 
      _data[valueEnum.Current.Name] = valueEnum.Current.Value.ToString(); 
     } 
    } 

    public void GetObjectData(SerializationInfo info, StreamingContext context) 
    { 
     foreach (var pair in _data) 
     { 
      info.AddValue(pair.Key, pair.Value); 
     } 
    } 
} 
4

एक विकल्प एक किराए संपत्ति का उपयोग कर और शब्दकोश कस्टम ISerializable प्रकार के अंदर होना है है, इस तरह आप:

+0

यदि आप कक्षाओं को नियंत्रित करते हैं तो यह बहुत अच्छी तरह से काम करता है, और आप 'CustomDictionarySerializer' मान प्रकार को सामान्य पैरामीटर बना सकते हैं ताकि आप किसी भी प्रकार के शब्दकोश को क्रमबद्ध (और deserialize) कर सकें। ध्यान दें कि संदर्भ प्रकार का कोई भी मूल्य "__type" संपत्ति (deserialization उद्देश्यों के लिए) जोड़ता है। इसके अलावा आपको कक्षा में 'डेटाकंट्रैक्ट' विशेषता का उपयोग करना होगा। –