2011-09-27 7 views
11

लागू करने वाले कस्टम संग्रह का जेसननेट सीरियलाइजेशन मेरे पास एक संग्रह कक्षा है जो आईनेमरेबल लागू करती है और मुझे इसके क्रमबद्ध संस्करण को deserializing में परेशानी हो रही है। मैं Json.net वी 4.0.2.13623आईएनमेर्यूरेबल <T>

यहाँ उपयोग कर रहा हूँ जब मैं यह क्रमानुसार मैं निम्नलिखित json मिलता जो कि मेरी समस्या

public class MyType 
{ 
    public int Number { get; private set; } 
    public MyType(int number) 
    { 
    this.Number = number; 
    } 
} 

public class MyTypes : IEnumerable<MyType> 
{ 
    private readonly Dictionary<int, MyType> c_index; 
    public MyTypes(IEnumerable<MyType> seed) 
    { 
    this.c_index = seed.ToDictionary(item => item.Number); 
    } 
    public IEnumerator<MyType> GetEnumerator() 
    { 
    return this.c_index.Values.GetEnumerator(); 
    } 
    IEnumerator IEnumerable.GetEnumerator() 
    { 
    return this.GetEnumerator(); 
    } 
    public int CustomMethod() 
    { 
    return 1; // Just for illustration 
    } 
} 

दिखाता है मेरे संग्रह वर्ग का एक सरल संस्करण है

[ 
    { 
    "Number": 1 
    }, 
    { 
    "Number": 2 
    } 
] 

लेकिन फिर जब मैं deserialize करने की कोशिश करता हूं तो मुझे निम्नलिखित अपवाद सिस्टम प्राप्त होता है। अपवाद: सूची प्रकार MyTypes

भी नहीं बना सकता है रीड क्रमबद्धता संकेत का उपयोग कर, लेकिन कोई सफलता

पड़ा है ये परीक्षण समारोह मैं

public void RoundTrip() 
{ 
    var _myTypes1 = new MyTypes(new[] { new MyType(1), new MyType(2) }); 
    var _jsonContent = JsonConvert.SerializeObject(_myTypes1, Formatting.Indented); 
    var _myTypes2 = JsonConvert.DeserializeObject<MyTypes>(_jsonContent); 
} 
public void RoundTripWithSettings() 
{ 
    var _myTypes1 = new MyTypes(new[] { new MyType(1), new MyType(2) }); 

    var _serializationSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Arrays }; 
    var _jsonContent = JsonConvert.SerializeObject(_myTypes1, Formatting.Indented, _serializationSettings); 
    var _myTypes2 = JsonConvert.DeserializeObject<MyTypes>(_jsonContent, _serializationSettings); 
} 

किसी को भी अपने स्वयं के संग्रह वस्तुओं को क्रमानुसार में कामयाब रहा है का इस्तेमाल किया है कर रहे हैं?

अग्रिम

पैट

+4

आपको कंक्रीट संग्रहों को क्रमबद्ध और deserialise जैसे सूची की तुलना में IENumerable की तुलना में करना चाहिए। कुछ deserialise करने के लिए, यह सिर्फ एक इंटरफेस के बजाय एक कार्यान्वयन की जरूरत है। – Deleted

+0

क्रिस, कुछ अन्य परिवर्तनों के साथ ReadOnlyCollection उपखंड के लिए बदला गया है लेकिन मैं संग्रह – pmcgrath

+1

संग्रह को deserialize पता कर सकते हैं वास्तव में आप एक IList का भी उपयोग कर सकते हैं। यह आपके लिए एक सूची तैयार करेगा। लेकिन IENumerable के लिए परिभाषित कोई डिफ़ॉल्ट संग्रह नहीं है। – Mithon

उत्तर

2

धन्यवाद मेरा मानना ​​है कि JSON नेट प्रकार यह करने के लिए deserializes के लिए एक parameterless निर्माता होने पर निर्भर करता है। एक deserialization बिंदु से यह पता नहीं है कि कन्स्ट्रक्टर को क्या प्रदान करना है।

अपने संग्रह के लिए के रूप में, फिर यह कैसे पता करने के लिए IEnumerable<T> के एक कार्यान्वयन है जो केवल परिभाषित करता है की गणना करने में कैसे संग्रह नहीं है कि यह कैसे को भरने के लिए पॉप्युलेट करने के लिए कैसे माना जाता है। आपको इसके बजाय कुछ मानक IEnumerable<MyType> (या सीधे IEnumerable<MyType> पर deserialize करना चाहिए जो मुझे लगता है कि JSON.NET समर्थन करता है) और फिर इसे अपने कन्स्ट्रक्टर को पास कर दें।

मैं निम्न में से सभी का मानना ​​है कि इस मामले में काम करना चाहिए:

var _myTypes2 = new MyTypes(JsonConvert.DeserializeObject<MyTypes[]>(_jsonContent)); 
var _myTypes2 = new MyTypes(JsonConvert.DeserializeObject<List<MyTypes>>(_jsonContent)); 
var _myTypes2 = new MyTypes(JsonConvert.DeserializeObject<IEnumerable<MyTypes>>(_jsonContent)); 

वैकल्पिक रूप से, हालांकि अधिक काम, आप जो JSON.NET अनुमति चाहिए अपने संग्रह पर IList की तरह कुछ को लागू कर सकते हैं अगर आप सीधे deserialized करने की जरूरत है अपने संग्रह को पॉप्युलेट करने के लिए IList विधियों का उपयोग करने के लिए।

+0

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

2

जेसन.नेट 6.0 रिलीज 3 और बाद में (मैंने 8.0.3 पर परीक्षण किया) के रूप में, यह स्वचालित रूप से तब तक काम करता है जब IEnumerable<MyType> को लागू करने वाले कस्टम क्लास में एक निर्माता होता है जो IEnumerable<MyType> इनपुट तर्क लेता है।

अपरिवर्तनीय नेट संग्रह में से भविष्य की सभी रचनाकारों के लिए:: अगर टी के अपने संग्रह, एक निर्माता कि IEnumerable तो Json.NET स्वचालित रूप से अपने संग्रह में deserializing काम करेंगे लेता है अन्यथा आप सभी बाहर हो release notes से नसीब की।

के बाद से सवाल में MyTypes वर्ग सिर्फ इस तरह के एक निर्माता है, यह अब सिर्फ काम करता है। प्रदर्शन पहेली: https://dotnetfiddle.net/LRJHbd

अनुपस्थित इस तरह के एक निर्माता, एक एक parameterless निर्माता जोड़ सकते हैं और ICollection<MyType> लागू करने के लिए (सिर्फ IEnumerable<MyType> के बजाय) एक काम Add(MyType item) विधि के साथ की आवश्यकता होगी। Json.NET तब संग्रह का निर्माण और पॉप्युलेट कर सकता है। या original answer में मध्यवर्ती संग्रह को deserialize।

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