序列化时json.net限制maxdepth [英] json.net limit maxdepth when serializing

查看:228
本文介绍了序列化时json.net限制maxdepth的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在将Asp.Net WebAPI与Entity Framework(带有延迟加载)一起使用,并使用Json.net将数据序列化为json,然后再将数据返回给客户端.

We're using Asp.Net WebAPI with Entity Framework (with lazy loading) and using Json.net for serializing the data to json before returning the data to the client.

我们正在经历间歇性的内存使用高峰,我们怀疑这可能是由于json.net导致的,在序列化数据时无法识别引用循环(因为Entity Framework可能会通过代理类对json进行监视,从而对伏都教进行了一些延迟加载.净)

We are experiencing intermittent sudden spikes in memory usage which we suspect might originate with json.net not recognizing reference loops when serializing data (since Entity Framework might be doing some lazy loading voodoo with proxy classes which goes under the radar of json.net)

我以为我可以限制Json.net允许序列化数据的深度(至少在发生这种情况时,我们会得到一个明智的异常,以便我们可以在数据模型中对其进行修复),但是我很快就发现了JsonSerializerSettings的MaxDepth属性仅在反序列化对象时起作用.

I thought I'd limit how deep Json.net was allowed to go to serialize data (at least then we'd get a sensible exception when this happens so we could fix it in the data model), but I soon discovered that the MaxDepth property of JsonSerializerSettings only kicks in when DEserializing objects.

序列化时,是否有任何已知的对json.net施加限制的方法?

Is there any known way of imposing a limit on json.net when serializing?

推荐答案

我想不出一种使用Json.NET进行即用的方法,因为(如您所正确观察到的) MaxDepth 会在序列化时被忽略.您可以做的是将 JsonTextWriter 子类化并进行检查你自己:

I can't think of a way to do this out-of-the-box with Json.NET, since (as you correctly observe) MaxDepth is ignored when serializing. What you could do is to subclass JsonTextWriter and do the checks yourself:

public class MaxDepthJsonTextWriter : JsonTextWriter
{
    public int? MaxDepth { get; set; }
    public int MaxObservedDepth { get; private set; }

    public MaxDepthJsonTextWriter(TextWriter writer, JsonSerializerSettings settings)
        : base(writer)
    {
        this.MaxDepth = (settings == null ? null : settings.MaxDepth);
        this.MaxObservedDepth = 0;
    }

    public MaxDepthJsonTextWriter(TextWriter writer, int? maxDepth)
        : base(writer)
    {
        this.MaxDepth = maxDepth;
    }

    public override void WriteStartArray()
    {
        base.WriteStartArray();
        CheckDepth();
    }

    public override void WriteStartConstructor(string name)
    {
        base.WriteStartConstructor(name);
        CheckDepth();
    }

    public override void WriteStartObject()
    {
        base.WriteStartObject();
        CheckDepth();
    }

    private void CheckDepth()
    {
        MaxObservedDepth = Math.Max(MaxObservedDepth, Top);
        if (Top > MaxDepth)
            throw new JsonSerializationException(string.Format("Depth {0} Exceeds MaxDepth {1} at path \"{2}\"", Top, MaxDepth, Path));
    }
}

然后,要手动生成JSON字符串,您可以像这样使用它:

Then, to manually generate a JSON string, you would use it like this:

var settings = new JsonSerializerSettings { MaxDepth = 10 };
string json;
try
{
    using (var writer = new StringWriter())
    {
        using (var jsonWriter = new MaxDepthJsonTextWriter(writer, settings))
        {
            JsonSerializer.Create(settings).Serialize(jsonWriter, myClass);
            // Log the MaxObservedDepth here, if you want to.
        }
        json = writer.ToString();
    }
    Debug.WriteLine(json);
}
catch (Exception ex)
{
    Debug.WriteLine(ex);
    throw;
}

演示小提琴此处.

由于您的标签包含,如果要在Web API调用中执行此检查,则可以按照Rick Strahl的说明为JSON创建自定义MediaTypeFormatter:

Since your tags include web-api, if you want to do this check inside web API calls, you could follow Rick Strahl's instructions to create a custom MediaTypeFormatter for JSON: Using an alternate JSON Serializer in ASP.NET Web API; then use the code above in the OnWriteToStreamAsync method when generating the json string.

这篇关于序列化时json.net限制maxdepth的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆