如何在Newtonsoft.Json反序列化时复用已实例化的SmallerData对象池
如何在Newtonsoft.Json反序列化时复用已实例化的SmallerData对象池
嘿,完全懂你想减少GC垃圾的诉求——对象池确实是这类场景的绝佳方案!你提到的ObjectFactory其实Newtonsoft.Json里并没有直接对应的设置项,但我们可以通过两种原生支持的方式实现这个需求,下面给你详细拆解:
方案一:自定义契约解析器(ContractResolver,推荐贴合框架逻辑)
这个方法会直接替换Json.NET创建SmallerData实例的底层逻辑,让它优先从你的对象池里取实例,而非通过反射新建。
首先写一个自定义契约解析器,把对象池作为依赖传入:
public class PooledContractResolver : DefaultContractResolver { private readonly List<SmallerData> _pooledData; public PooledContractResolver(List<SmallerData> pooledData) { _pooledData = pooledData; } protected override JsonObjectContract CreateObjectContract(Type objectType) { var contract = base.CreateObjectContract(objectType); // 仅针对SmallerData类型替换实例创建逻辑 if (objectType == typeof(SmallerData)) { contract.DefaultCreator = () => { if (_pooledData.Count == 0) { // 池空时的兜底逻辑,可根据需求改成抛异常或其他策略 return new SmallerData(); } var instance = _pooledData[0]; _pooledData.RemoveAt(0); return instance; }; // 若SmallerData有带参构造函数,需额外处理DefaultCreatorParameters } return contract; } }
然后在反序列化时配置这个解析器:
public class Example { // 初始化包含3个实例的对象池 private List<SmallerData> _pooledData = new() { new SmallerData(), new SmallerData(), new SmallerData() }; public MainData DeserializeFromPool(string jsonString) { var settings = new JsonSerializerSettings { ContractResolver = new PooledContractResolver(_pooledData), // 因为你的JSON里带$type,要开启类型名称处理 TypeNameHandling = TypeNameHandling.Auto }; return JsonConvert.DeserializeObject<MainData>(jsonString, settings); } }
这个方案的优势是完全融入Json.NET的原生序列化流程,属性填充等工作都由框架自动完成,不用手动处理。
方案二:自定义Json转换器(JsonConverter,适合复杂场景)
如果你的SmallerData有特殊的初始化逻辑,或者你想完全掌控反序列化的每一步,可以用自定义转换器:
public class PooledSmallerDataConverter : JsonConverter<SmallerData> { private readonly List<SmallerData> _pooledData; public PooledSmallerDataConverter(List<SmallerData> pooledData) { _pooledData = pooledData; } public override SmallerData ReadJson(JsonReader reader, Type objectType, SmallerData existingValue, bool hasExistingValue, JsonSerializer serializer) { // 从对象池获取实例,池空则新建兜底 var instance = _pooledData.Count > 0 ? _pooledData[0] : new SmallerData(); if (_pooledData.Count > 0) { _pooledData.RemoveAt(0); } // 让框架自动把JSON属性值填充到实例中 serializer.Populate(reader, instance); return instance; } public override void WriteJson(JsonWriter writer, SmallerData value, JsonSerializer serializer) { // 序列化用默认逻辑即可 serializer.Serialize(writer, value); } }
使用时把转换器加入序列化配置:
public MainData DeserializeFromPool(string jsonString) { var settings = new JsonSerializerSettings { Converters = new List<JsonConverter> { new PooledSmallerDataConverter(_pooledData) }, TypeNameHandling = TypeNameHandling.Auto }; return JsonConvert.DeserializeObject<MainData>(jsonString, settings); }
关键注意事项
- 确保对象池里的实例是干净状态:如果实例被复用前有残留数据,记得在放回池时重置属性(比如把
myInt设为0),避免脏数据问题。 - 池空时的兜底逻辑可按需调整:比如改成阻塞等待新实例、抛自定义异常等,根据你的业务场景来定。
- 若
SmallerData有带参构造函数,需要在契约解析器里额外处理DefaultCreatorParameters,或者在转换器里手动完成构造逻辑。
备注:内容来源于stack exchange,提问作者OeilDeLance
相关产品推荐
相关产品推荐

