JSON对象不会为大数据序列化

时间:2016-08-01 11:34:45

标签: c# angularjs json asp.net-mvc serialization

我正在尝试使用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 };
    }
}

Angular JSON结果类:

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

JSON结果类:

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);
    }
}

这里我定义了传递对象的AngularJson方法,并覆盖了将对象转换为JSON的ExecuteResult方法。

因此我的SerializeData方法正在传递Response并转换为JSON中的Objet,例如Data.ToJson()

请告诉我你的建议。

1 个答案:

答案 0 :(得分:1)

您的问题是您将大数据序列化到服务器内存中的字符串,然后将整个字符串写入HttpResponseBase(默认情况下也会缓存所有内容),并且在过程中的某个地方耗尽了内存,可能超过了maximum c# string length

减少内存使用的一种方法是使用HttpResponseBase.OutputStream直接序列化为JsonSerializer.Serialize()。这避免了中间字符串表示。

可能还需要设置HttpResponseBase.Buffer = false,如果是,请按照Unbuffered Output Very Slow中给出的建议将输出流包装在BufferedStream中。< / p>

可以使用以下扩展方法:

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());