2014-09-30 75 views
4

免責聲明:我經歷了本文提供的大多數解決方案,但其中大部分都是在反序列化時討論OOM異常。使用Json.Net序列化對象會導致內存不足異常

我想使用Json.Net將對象(它是一棵樹)序列化爲Json。一切工作正常的小對象,但我得到OOM異常,當我嘗試與大對象。由於它與相同數據類型的較小對象一起工作,我假定沒有循環引用(我檢查過它的數據結構)。 有沒有一種方法可以將我的對象轉換爲流(這是一個Windows應用商店應用)並使用該流生成Json?

public static async Task<bool> SerializeIntoJson<T>(string fileName, StorageFolder destinationFolder, Content content) 
    { 
     ITraceWriter traceWriter = new MemoryTraceWriter(); 
     try 
     { 

      string jsonString = JsonConvert.SerializeObject(content, Formatting.Indented, new JsonSerializerSettings 
      { 
       PreserveReferencesHandling = PreserveReferencesHandling.Objects, 
       TypeNameHandling = TypeNameHandling.All, 
       Error = ReportJsonErrors, 
       TraceWriter = traceWriter, 
       StringEscapeHandling = StringEscapeHandling.EscapeNonAscii 
      }); 
      System.Diagnostics.Debug.WriteLine(traceWriter); 

      StorageFile file = await destinationFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting); 
      await Windows.Storage.FileIO.WriteTextAsync(file, jsonString); 
      return true; 
     } 
     catch (NullReferenceException nullException) 
     { 
      System.Diagnostics.Debug.WriteLine(traceWriter); 
      logger.LogError("Exception happened while serializing input object, Error: " + nullException.Message); 
      return false; 
     } 
     catch (Exception e) 
     { 
      System.Diagnostics.Debug.WriteLine(traceWriter); 
      logger.LogError("Exception happened while serializing input object, Error: " + e.Message, e.ToString()); 
      return false; 
     } 
    } 

爲了我的對象轉換成流,我發現代碼中使用的BinaryFormatter這是不是在Windows商店應用的DLL可用。

+1

嘗試使用'JsonSerializer'以'StreamReader'結合所概述[這裏](HTTP:/ /stackoverflow.com/questions/8157636/can-json-net-serialize-deserialize-to-from-a-stream)。 – 2014-09-30 19:18:32

+0

我確實看了看代碼,並將我帶入了一個問題:有沒有辦法將我的對象轉換爲流(這是Windows應用商店應用)? – 2014-09-30 19:35:38

+1

這就是串行器的功能。它採用所有的屬性並將它們轉換爲字符串。在這種情況下,不用返回字符串,它可以將它們直接存入流(例如文件流),以便它們不在內存中。 – 2014-09-30 19:42:11

回答

4

根據對問題的評論中的建議更新了代碼,This Works!

public static async Task<bool> SerializeIntoJson<T>(string fileName, StorageFolder destinationFolder, Content content) 
    { 
     try 
     { 
      StorageFile file = await destinationFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting); 
      using (var stream = await file.OpenStreamForWriteAsync()) 
      { 

       StreamWriter writer = new StreamWriter(stream); 
       JsonTextWriter jsonWriter = new JsonTextWriter(writer); 
       JsonSerializer ser = new JsonSerializer(); 

       ser.Formatting = Newtonsoft.Json.Formatting.Indented; 
       ser.PreserveReferencesHandling = PreserveReferencesHandling.Objects; 
       ser.TypeNameHandling = TypeNameHandling.All; 
       ser.Error += ReportJsonErrors; 

       ser.Serialize(jsonWriter, content); 

       jsonWriter.Flush(); 

      } 
      return true; 
     } 
     catch (NullReferenceException nullException) 
     { 

      logger.LogError("Exception happened while serializing input object, Error: " + nullException.Message); 
      return false; 
     } 
     catch (Exception e) 
     { 

      logger.LogError("Exception happened while serializing input object, Error: " + e.Message, e.ToString()); 
      return false; 
     } 
    } 
4

這是由於您嘗試序列化的記錄數量非常大,佔用大量內存。我發現這個錯誤的解決方案是使用StreamWriter(JsonWriter或TextWriter)直接寫入文檔。

如果你有對象使用TextWrite

using (TextWriter textWriter = File.CreateText("LocalJsonFile.json")) 
{ 
    var serializer = new JsonSerializer(); 
    serializer.Serialize(textWriter , yourObject); 
} 

如果列使用的StringWriter

StringBuilder sb = new StringBuilder(); 
    StringWriter sw = new StringWriter(sb); 

    using(JsonWriter textWriter = new JsonTextWriter(sw)) 
    { 
    var serializer = new JsonSerializer(); 
    serializer.Serialize(textWriter, yourObject); 
    }