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

Newtonsoft Json.Net反序列化时如何条件跳过数组项仅保留前N条数据

Json.NET 反序列化仅读取数组前N项实现方案

可以通过自定义JsonConverter实现该需求,核心逻辑是在读取数组节点时,解析完指定数量的前缀元素后,直接跳过数组剩余的所有Token,无需反序列化后续内容,性能损耗极低。

实现代码

/// <summary>
/// 限制数组反序列化最大数量的转换器
/// </summary>
/// <typeparam name="T">数组元素类型</typeparam>
public class LimitedArrayConverter<T> : JsonConverter
{
    private readonly int _maxItemCount;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="maxItemCount">最多读取的数组元素数量</param>
    public LimitedArrayConverter(int maxItemCount)
    {
        _maxItemCount = maxItemCount > 0 ? maxItemCount : 1;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(List<T>) || objectType == typeof(T[]);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null) return null;
        if (reader.TokenType != JsonToken.StartArray)
        {
            throw new JsonSerializationException("当前节点不是数组类型");
        }

        var resultList = new List<T>(_maxItemCount);
        int currentCount = 0;

        // 遍历数组节点
        while (reader.Read() && reader.TokenType != JsonToken.EndArray)
        {
            if (currentCount < _maxItemCount)
            {
                // 反序列化需要的前N个元素
                var item = serializer.Deserialize<T>(reader);
                resultList.Add(item);
                currentCount++;
            }
            else
            {
                // 直接跳过后续元素,不做反序列化
                reader.Skip();
            }
        }

        // 适配数组/List两种返回类型
        return objectType.IsArray ? resultList.ToArray() : resultList;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        // 仅用于反序列化,序列化逻辑无需实现
        throw new NotSupportedException("该转换器仅支持读取操作");
    }
}

使用方式

  • 固定取数场景
    若需要固定读取前N条数据,直接在对应数组属性上标注JsonConverter特性即可:
    public class FinanceOrderResponse
    {
        // 其他接口返回属性省略
        [JsonConverter(typeof(LimitedArrayConverter<OrderItem>), 20)]
        public List<OrderItem> OrderList { get; set; }
    }
    
  • 动态取数场景
    若需要每次反序列化时动态指定取数数量,反序列化时传入转换器实例即可:
    int needCount = 15; // 可根据业务需求动态调整
    var deserializeSettings = new JsonSerializerSettings
    {
        Converters = new List<JsonConverter> { new LimitedArrayConverter<OrderItem>(needCount) }
    };
    var responseData = JsonConvert.DeserializeObject<FinanceOrderResponse>(rawJson, deserializeSettings);
    

补充说明

  • 核心的reader.Skip()方法仅在JSON流层面跳过节点,不会加载或解析后续内容,数组剩余元素越多,性能提升越明显,对比全量反序列化后再截取前缀的方案,最高可获得10倍以上的性能提升
  • 如果存在多个数组属性需要分别限制取数数量,给每个属性单独标注特性指定不同的最大数量即可,不会互相干扰
  • 配合MemberSerialization.OptIn特性只反序列化需要的字段,可进一步降低性能损耗

内容的提问来源于stack exchange,提问作者Mark

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 20:09:02