Json.NETcachingtypes的序列化信息?
在.NET世界中,当谈到对象序列化时,通常会在运行时检查对象的字段和属性。 在处理大量对象时,使用reflection来处理这个工作通常是很慢的,是不可取的。 另一种方式是使用IL发射或构buildperformance树,从而提供显着的性能增益而不是reflection。 而后者是现代图书馆在处理序列化时select的。 但是,在运行时构build和发布IL需要时间,只有将这些信息caching并重新用于相同types的对象时,投资才会被偿还。
当使用Json.NET时,我不清楚上面使用了哪种方法,如果后者确实使用,是否使用caching。
例如,当我这样做时:
JsonConvert.SerializeObject(new Foo { value = 1 });
Json.NET是否构build了Foo的成员访问信息和caching以供以后重用?
Json.NETcachingIContractResolver
类DefaultContractResolver
和CamelCasePropertyNamesContractResolver
序列化信息。 除非您指定了自定义合约parsing器,否则这些信息将被caching并重新使用。
对于DefaultContractResolver
,Json.NET在应用程序没有指定自己的合约parsing器时使用全局静态实例。 另一方面, CamelCasePropertyNamesContractResolver
维护在所有实例之间共享的静态表。 (我相信不一致性来自遗留问题,详情请参阅此处 。)
这两种types的devise都是完全线程安全的,因此线程之间的共享应该不成问题。
如果您select制作您自己的合约parsing器,那么只有caching并重新使用合约parsing器实例本身时,才会caching并重用types信息。 因此,对于“无状态”parsing器(基于当前实例被序列化或其他运行时条件不修改其返回值的parsing器),Newtonsoft build议 :
在应用程序中caching合约parsing器的实例以获得最佳性能。
在DefaultContractResolver
的子类中保证caching的一个策略是使其构造函数受到保护或保密,并提供一个全局静态实例。 (当然这只有在parsing器总是返回相同的结果时才是合适的)。例如,受这个问题的启发,下面是一个强调合同parsing器的案例:
public class PascalCaseToUnderscoreContractResolver : DefaultContractResolver { protected PascalCaseToUnderscoreContractResolver() : base() { } // As of 7.0.1, Json.NET suggests using a static instance for "stateless" contract resolvers, for performance reasons. // http://www.newtonsoft.com/json/help/html/ContractResolver.htm // http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Serialization_DefaultContractResolver__ctor_1.htm // "Use the parameterless constructor and cache instances of the contract resolver within your application for optimal performance." static PascalCaseToUnderscoreContractResolver instance; // Using an explicit static constructor enables lazy initialization. static PascalCaseToUnderscoreContractResolver() { instance = new PascalCaseToUnderscoreContractResolver(); } public static PascalCaseToUnderscoreContractResolver Instance { get { return instance; } } static string PascalCaseToUnderscore(string name) { if (name == null || name.Length < 1) return name; var sb = new StringBuilder(name); for (int i = 0; i < sb.Length; i++) { var ch = char.ToLowerInvariant(sb[i]); if (ch != sb[i]) { if (i > 0) // Handle flag delimiters { sb.Insert(i, '_'); i++; } sb[i] = ch; } } return sb.ToString(); } protected override string ResolvePropertyName(string propertyName) { return PascalCaseToUnderscore(propertyName); } }
你会喜欢哪个:
var json = JsonConvert.SerializeObject(someObject, new JsonSerializerSettings { ContractResolver = PascalCaseToUnderscoreContractResolver.Instance });