2016-08-01 50 views
2

我想在JSON中序列化數據。但我面臨異常。JSON對象不會序列化爲巨大的數據

OutOfMemoryException未被用戶代碼處理。
型 '的System.OutOfMemoryException' 的異常出現在Newtonsoft.Json.dll但在用戶代碼中沒有處理

下面我定義我的代碼:

主控制器:

public class TrackingController : BaseAngularController 
{ 
    var lstDetails = _services.GetTrackingDetailsByAWBIds(awbids, awbType); 
    if (lstDetails != null) 
    { 
     return AngularJson(lstDetails); 
    } 
} 

基地控制器:

public abstract class BaseAngularController : Controller 
{ 
    public AngularJsonResult<T> AngularJson<T>(T model) 
    { 
     return new AngularJsonResult<T>() { Data = model }; 
    } 
} 

角JSON Result類:

public class AngularJsonResult<T> :AngularJsonResult 
{ 
    public new T Data 
    { 
     get { return (T)base.Data; } 
     set { base.Data = value; } 
    } 
} 

JSON Result類:

public class AngularJsonResult : JsonResult 
{ 
    public override void ExecuteResult(ControllerContext context) 
    { 
     DoUninterestingBaseClassStuff(context); 

     SerializeData(context.HttpContext.Response); 
    } 

    private void DoUninterestingBaseClassStuff(ControllerContext context) 
    { 
     if (context == null) 
     { 
      throw new ArgumentNullException("context"); 
     } 

     var response = context.HttpContext.Response; 
     response.ContentType = string.IsNullOrEmpty(ContentType) ? "application/json" : ContentType; 

     if (ContentEncoding != null) 
     { 
      response.ContentEncoding = ContentEncoding; 
     } 
    } 

    protected virtual void SerializeData(HttpResponseBase response) 
    { 
     if (ErrorMessages.Any()) 
     { 
      Data = new 
      { 
       ErrorMessage = string.Join("\n", ErrorMessages), 
       ErrorMessages = ErrorMessages.ToArray() 
      }; 

      response.StatusCode = 400; 
     } 

     if (Data == null) return; 

     response.Write(Data.ToJson()); 
    } 
} 

序列化對象JSON:

public static class JsonExtensions 
{ 
    public static string ToJson<T>(this T obj, bool includeNull = true) 
    { 
     var settings = new JsonSerializerSettings 
     { 
      ContractResolver = new CamelCasePropertyNamesContractResolver(), 
      Converters = new JsonConverter[] { new StringEnumConverter() }, 
      ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore,//newly added 
      //PreserveReferencesHandling =Newtonsoft.Json.PreserveReferencesHandling.Objects, 
      NullValueHandling = includeNull ? NullValueHandling.Include : NullValueHandling.Ignore 
     }; 
     return JsonConvert.SerializeObject(obj, settings); 
    } 
} 

她e我定義了AngularJson傳遞對象的方法並覆蓋ExecuteResult將Object轉換爲JSON的方法。

所以我SerializeData方法傳遞Response並轉換爲Objet公司在JSON,像Data.ToJson()

請讓我知道你的建議。

+0

此代碼部署,在測試服務器上,或者是你通過一個測試它IDE?你在用什麼IDE? –

+0

是這個代碼部署在測試服務器上。 –

+0

所以這可能是一個JVM內存問題 - 這聽起來像你沒有分配足夠的內存來處理你想要序列化的任何東西。數據有多大? –

回答

1

你的問題是,你是序列化您的龐大的數據爲字符串在內存中的服務器上,然後寫整個字符串到HttpResponseBase(也緩衝由默認的一切),並在某處運行內存過程,可能超過maximum c# string length

減少內存使用的一種方法是使用JsonSerializer.Serialize()直接序列化到HttpResponseBase.OutputStream。這避免了中間字符串表示。

可能還需要設置HttpResponseBase.Buffer = false,如果是這樣,請按照Unbuffered Output Very Slow給出的建議,並在BufferedStream包裝輸出流。

下面的擴展方法可以用於此:

public static class HttpResponseBaseExtensions 
{ 
    public static void WriteJson<T>(this HttpResponseBase response, T obj, bool useResponseBuffering = true, bool includeNull = true) 
    { 
     var contentEncoding = response.ContentEncoding ?? Encoding.UTF8; 
     if (!useResponseBuffering) 
     { 
      response.Buffer = false; 

      // use a BufferedStream as suggested in //https://stackoverflow.com/questions/26010915/unbuffered-output-very-slow 
      var bufferedStream = new BufferedStream(response.OutputStream, 256 * 1024); 
      bufferedStream.WriteJson(obj, contentEncoding, includeNull); 
      bufferedStream.Flush(); 
     } 
     else 
     { 
      response.OutputStream.WriteJson(obj, contentEncoding, includeNull); 
     } 
    } 

    static void WriteJson<T>(this Stream stream, T obj, Encoding contentEncoding, bool includeNull) 
    { 
     var settings = new JsonSerializerSettings 
     { 
      ContractResolver = new CamelCasePropertyNamesContractResolver(), 
      Converters = new JsonConverter[] { new StringEnumConverter() }, 
      ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore,//newly added 
      //PreserveReferencesHandling =Newtonsoft.Json.PreserveReferencesHandling.Objects, 
      NullValueHandling = includeNull ? NullValueHandling.Include : NullValueHandling.Ignore 
     }; 
     var serializer = JsonSerializer.CreateDefault(settings); 
     var textWriter = new StreamWriter(stream, contentEncoding); 
     serializer.Serialize(textWriter, obj); 
     textWriter.Flush(); 
    } 
} 

然後使用擴展方法代替response.Write(Data.ToJson());