In .NET world, when it comes to object serialization, it usually goes into inspecting the object's fields and properties at runtime. Using reflection for this job is usually slow and is undesirable when dealing with large sets of objects. The other way is using IL emit or building expression trees that provide significant performance gain over reflection. And the latter is most modern libraries pick when dealing with serialization. However building and emitting IL at runtime takes time, and the investment is only paid back if this information is cached and reused for objects of the same type.

当使用Json时.NET中,我不清楚使用了上述哪种方法,如果确实使用了后者,是否使用了缓存.

For example, when I do:

JsonConvert.SerializeObject(new Foo { value = 1 });

Does Json.NET build the Foo's member access info and cache to reuse it later?

推荐答案

Yes, it does. Json.NET在其IContractResolver个类DefaultContractResolverCamelCasePropertyNamesContractResolver中缓存类型序列化信息.除非指定自定义合同解析程序,否则将缓存并重用此信息.

For DefaultContractResolver a global static instance is maintained internally that Json.NET uses whenever the application does not specify its own contract resolver. CamelCasePropertyNamesContractResolver, on the other hand, maintains static tables that are shared across all instances. (I believe the inconsistency arises from legacy issues; see here for details.)

Both of these types are designed to be fully thread-safe so sharing between threads should not be a problem.

如果 Select 实现和实例化您自己的协定解析器,则只有在缓存和重用协定解析器实例本身的情况下,才会缓存和重用类型信息.因此,NewtonSoft recommends:

For performance you should create a contract resolver once and reuse instances when possible. Resolving contracts is slow and implementations of IContractResolver typically cache contracts.

If memory consumption is a problem无论出于何种原因,您需要最小化缓存契约永久占用的内存,您都可以构造自己的本地实例DefaultContractResolver(或某个自定义子类),使用该实例进行序列化,然后立即删除对它的所有引用,例如:

public class JsonExtensions
{
    public static string SerializeObjectNoCache<T>(T obj, JsonSerializerSettings settings = null)
    {
        settings = settings ?? new JsonSerializerSettings();
        bool reset = (settings.ContractResolver == null);
        if (reset)
            // To reduce memory footprint, do not cache contract information in the global contract resolver.
            settings.ContractResolver = new DefaultContractResolver();
        try
        {
            return JsonConvert.SerializeObject(obj, settings);
        }
        finally
        {
            if (reset)
                settings.ContractResolver = null;
        }
    }
}

如果您使用的是CamelCasePropertyNamesContractResolver,请使用适当的naming strategy切换到DefaultContractResolver,例如:

settings.ContractResolver = new DefaultContractResolver { NamingStrategy = new CamelCaseNamingStrategy() };

大多数高速缓存的契约存储器(100)最终将被垃圾收集.当然,通过这样做,serialization performance may suffer substantially.(包含关于例如enum种类型和数据协定属性的反映信息的一些表是全局共享的,而不是回收的.)

For further information看牛顿软件公司的Performance Tips: Reuse Contract Resolver.

Json相关问答推荐

两种情况下过滤的JOLT规范

从Razor Pages的AJAX Json呈现DataTables问题.Net GET

如何在VegaLite中应用Times New Roman,CaliBiri字体

在Reaction中从JSON文件中筛选数组

褐煤面积图中的分选问题

如果主对象中已存在属性,则不应在Jolt中引用次对象

用 Jolt 替换 JSON 中的值

迭代powershell双维json对象

将不带正文的 CURL POST 转换为 RESTRequest Delphi 代码 / 为 Dropbox API /get_current_account 端点编写 Delphi 代码

使用jq根据对象中键的值查找对象

如何在不使用 Newtonsoft.JSON 的情况下序列化/反序列化

使用 Jolt 变换将平面 json 转换为具有多个数组的嵌套 Json

如何在 Dart 中与多个 map (字典)相交

Vue 3如何将参数作为json发送到axios get

如何使用 boost::json::value 调用无参数函数

apple-app-site-association json 文件是否会在应用程序中更新?

如何在 django rest 框架中定义列表字段?

在自定义 JsonConverter 的 ReadJson 方法中处理空对象

将 javascript 对象或数组转换为 json 以获取 ajax 数据

为什么 JavaScript 的 eval 需要括号来判断 JSON 数据?