我正在使用NETCore 3.0的System.Text.Json命名空间中的新JsonSerializer来反序列化Json文档,如下所示:

var result = JsonSerializer.Deserialize<Response>(json, options);


响应定义为:

public class Response
{
    public string Foo { get; set; }
    public JsonElement Bar { get; set; }
}


JsonDocument实现IDisposable的事实使我想知道是否通过保留对JsonDocument中可以包含的元素(Bar)的引用,是否会造成内存泄漏?

请注意,通常,我避免像这样将数据存储为“变量”类型。不幸的是,Bar属性值的结构在编译时是未知的。

我的怀疑来自System.Text.Json宣传了懒惰评估的优势,我不确定这是否涉及延迟的I / O。

最佳答案

从对源(https://github.com/dotnet/corefx/blob/master/src/System.Text.Json/src/System/Text/Json/Document/JsonDocument.cs)的简短调查来看,JsonDocument Dispose似乎将“租用”字节返回到共享数组池并进行了一些常规清理。
JsonDocument的某些实例被标记为不是一次性的,在这种情况下,Dispose将不会执行任何操作。
您可以使用反射检查实例的此标志-如果您的实例的内部IsDisposableable标志没有设置为true,则无需担心,因为Dispose不会做任何事情。

我认为在正常情况下,JsonDocument解析器应自行清理,解析器完成后不应再有任何租借字节或内部数据。

尽管可能会更改并仅存储对所需元素的引用,但不依赖特定的实现始终是安全的。您可能应该将JSON元素重新映射到模型,我认为这是JSON反序列化的全部目的

快速测试:

        var parentField = result.Bar.GetType().GetMember("_parent", MemberTypes.Field, BindingFlags.Instance | BindingFlags.NonPublic)[0] as FieldInfo;
        var parentDocument = parentField.GetValue(result.Bar);

        var isDisposableProperty = parentDocument.GetType().GetProperty("IsDisposable", BindingFlags.Instance | BindingFlags.NonPublic) as PropertyInfo;
        Console.WriteLine(isDisposableProperty.GetValue(parentDocument)); // false


证明JsonElement持有的JsonDocument实例不是一次性的。

07-26 04:47