.NET

2015-08-26 3 views
26

में बड़ी जेसन फ़ाइल को पार्स करना मैंने जेसन.नेट का "जेसनकॉन्टर.डिसरियललाइज (जेसन)" विधि का उपयोग किया है, अब तक जो काफी अच्छा काम करता है और ईमानदार होने के लिए, मुझे इससे ज्यादा कुछ नहीं चाहिए।.NET

मैं पृष्ठभूमि (कंसोल) ऐप पर काम कर रहा हूं जो लगातार विभिन्न यूआरएल से जेसन सामग्री डाउनलोड करता है, फिर परिणाम को नेट ऑब्जेक्ट की सूची में deserializes।

using (WebClient client = new WebClient()) 
{ 
     string json = client.DownloadString(stringUrl); 

     var result = JsonConvert.DeserializeObject<List<Contact>>(json); 

} 

सरल कोड स्निपेट के ऊपर शायद सही प्रतीत नहीं होता है, लेकिन यह काम करता है। जब फ़ाइल बड़ी होती है (15000 संपर्क - 48 एमबी फ़ाइल), JsonConvert.DeserializeObject समाधान नहीं है और रेखा एक अपवाद प्रकार JsonReaderException फेंकता है।

डाउनलोड जेसन एक सरणी है और इस तरह नमूना दिखता है। संपर्क deserialized जेसन ऑब्जेक्ट के लिए एक कंटेनर वर्ग है।

[ 
    { 
    "firstname": "sometext", 
    "lastname": "sometext" 
    }, 
    { 
    "firstname": "sometext", 
    "lastname": "sometext" 
    }, 
    { 
    "firstname": "sometext", 
    "lastname": "sometext" 
    }, 
    { 
    "firstname": "sometext", 
    "lastname": "sometext" 
    } 
] 

मेरा प्रारंभिक अनुमान यह स्मृति से बाहर है। जिज्ञासा से बाहर, मैंने इसे जेएरे के रूप में पार्स करने की कोशिश की जिसके कारण भी एक ही अपवाद हुआ।

मैंने जेसन.Net दस्तावेज़ में गोता लगाने और समान धागे पढ़ने के लिए शुरू कर दिया है। चूंकि मैंने अभी तक एक समाधान समाधान तैयार नहीं किया है, इसलिए मैंने यहां एक प्रश्न पोस्ट करने का फैसला किया है।

मैं किसी भी सलाह/कोड स्निपेट की सराहना करता हूं जो इस मुद्दे पर शोध करने, इसके बारे में और अधिक सीखने में मदद कर सकता है।

धन्यवाद :)

अद्यतन: लाइन द्वारा लाइन deserializing है, मैं एक ही त्रुटि मिली: "।, स्थिति 1. [पथ ', लाइन 600,003" तो मैंने उन दोनों को डाउनलोड करने के लिए किया था और उन्हें नोटपैड ++ में चेक किया था। मैंने देखा कि यदि 12000 वें तत्व के बाद सरणी की लंबाई 12000 से अधिक है, तो "[" बंद है और एक और सरणी शुरू होती है। दूसरे शब्दों में, json वास्तव में इस तरह दिखता है:

[ 
    { 
    "firstname": "sometext", 
    "lastname": "sometext" 
    }, 
    { 
    "firstname": "sometext", 
    "lastname": "sometext" 
    }, 
    { 
    "firstname": "sometext", 
    "lastname": "sometext" 
    }, 
    { 
    "firstname": "sometext", 
    "lastname": "sometext" 
    } 
] 
[ 
    { 
    "firstname": "sometext", 
    "lastname": "sometext" 
    }, 
    { 
    "firstname": "sometext", 
    "lastname": "sometext" 
    }, 
    { 
    "firstname": "sometext", 
    "lastname": "sometext" 
    }, 
    { 
    "firstname": "sometext", 
    "lastname": "sometext" 
    } 
] 
+7

'और लाइन JsonReaderException.' की एक अपवाद प्रकार क्या अपवाद संदेश है फेंकता है? कोई आंतरिक अपवाद? – Eser

+0

जेएसओएन सामग्री को पढ़ने के बाद अतिरिक्त पाठ का सामना करना पड़ा: [। पथ '', लाइन 600003, स्थिति 1. "- यह अपवाद संदेश – Yavarino

+3

@Yavarski क्या आप निश्चित हैं कि आप JSON मान्य हैं? –

उत्तर

26

आपने उसे अपने अद्यतन में निदान किया है, मुद्दा यह है कि JSON एक बंद ] एक उद्घाटन [ द्वारा तुरंत बाद अगले सेट शुरू करने के लिए है। जब यह पूरी तरह से लिया जाता है तो यह प्रारूप JSON को अमान्य बनाता है, और यही वजह है कि जेसन.Net एक त्रुटि फेंकता है। सौभाग्य से यह समस्या अक्सर पर्याप्त होती है कि जेसन.Net वास्तव में इसके साथ निपटने के लिए एक विशेष सेटिंग है। यदि आप JSON को पढ़ने के लिए सीधे JsonTextReader का उपयोग करते हैं, तो आप SupportMultipleContent ध्वज को true पर सेट कर सकते हैं, और उसके बाद प्रत्येक आइटम को व्यक्तिगत रूप से deserialize करने के लिए एक लूप का उपयोग कर सकते हैं। यह आपको गैर-मानक JSON को सफलतापूर्वक और मेमोरी कुशल तरीके से संसाधित करने की अनुमति दे सकता है, इस पर ध्यान दिए बिना कि कितने सरणी हैं या प्रत्येक सरणी में कितनी चीज़ें हैं।

using (WebClient client = new WebClient()) 
    using (Stream stream = client.OpenRead(stringUrl)) 
    using (StreamReader streamReader = new StreamReader(stream)) 
    using (JsonTextReader reader = new JsonTextReader(streamReader)) 
    { 
     reader.SupportMultipleContent = true; 

     var serializer = new JsonSerializer(); 
     while (reader.Read()) 
     { 
      if (reader.TokenType == JsonToken.StartObject) 
      { 
       Contact c = serializer.Deserialize<Contact>(reader); 
       Console.WriteLine(c.FirstName + " " + c.LastName); 
      } 
     } 
    } 

पूर्ण यहाँ डेमो: https://dotnetfiddle.net/2TQa8p

+0

यह शानदार है! धन्यवाद ब्रायन! – Yavarino

+0

खुशी है कि मैं मदद कर सकता हूं। –

+0

मैं अपना खुद का पार्सर बनाने के करीब था। यह बहुत बढ़िया है, ब्रायन धन्यवाद। –

4

मैं 5 जीबी का फ़ाइल आकार के लिए अजगर में इसी तरह की बात कर चुके हैं। मैंने फ़ाइल को कुछ अस्थायी स्थान में डाउनलोड किया है और एसएक्स कैसे काम करता है, इस तरह एक JSON ऑब्जेक्ट बनाने के लिए इसे लाइन द्वारा लाइन पढ़ें। ग # json.net का उपयोग कर के लिए, आप फाइल डाउनलोड, धारा रीडर का उपयोग फ़ाइल को पढ़ने, और JsonTextReader है कि धारा गुजरती हैं और JTokens.ReadFrom (अपने JSonTextReader वस्तु)

+0

यह समझ में आता है। मैं कोशिश करूँगा और यहां अपडेट पोस्ट करूंगा। एक मिल का धन्यवाद। – Yavarino

+0

नीचे "क्रिस्टियन" उत्तर की तलाश करें। उन्होंने कोड को कार्यान्वित किया है जो मैंने उपरोक्त समझाया है, लेकिन मुझे "क्रिस्टियन" दृष्टिकोण बेहतर पसंद है :) – nixdaemon

12

Json.NET से सीधे deserializing का समर्थन करता है का उपयोग कर JObject को यह पार्स करने के लिए कर सकते हैं एक धारा। यहां JSON स्ट्रिंग को एक टुकड़ा पढ़ने के बजाय StreamReader का उपयोग करके अपने JSON को deserialize करने का एक तरीका है, जिसमें पूरे JSON स्ट्रिंग को स्मृति में लोड किया गया है।

using (WebClient client = new WebClient()) 
{ 
    using (StreamReader sr = new StreamReader(client.OpenRead(stringUrl))) 
    { 
     using (JsonReader reader = new JsonTextReader(sr)) 
     { 
      JsonSerializer serializer = new JsonSerializer(); 

      // read the json from a stream 
      // json size doesn't matter because only a small piece is read at a time from the HTTP request 
      IList<Contact> result = serializer.Deserialize<List<Contact>>(reader); 
     } 
    } 
} 

संदर्भ: JSON.NET Performance Tips

+1

यह कोड पूरी स्ट्रीम को स्मृति में लोड नहीं कर सकता है, लेकिन निश्चित रूप से संपर्कों की पूरी सूची को स्मृति में लोड कर देगा। जब तक संपर्क ऑब्जेक्ट स्ट्रीम से बड़ी मात्रा में डेटा फेंक नहीं देता है, तब तक आपने अपनी मेमोरी समस्या को डाउनस्ट्रीम को धक्का दिया है। –