You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 09:04:32