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

如何使用C#获取JSON项数量及通过JObject遍历JSON树

C# 使用JObject遍历JSON树、统计JSON项数量实现方案

所有实现基于Newtonsoft.Json(Json.NET),使用前需要先引入Newtonsoft.Json.Linq命名空间。

遍历JSON树结构

JSON本身是递归嵌套的结构,JToken是JObject(JSON对象)、JArray(JSON数组)、JValue(基础值类型:字符串/数字/布尔/null)的公共基类,遍历核心逻辑是判断当前节点类型,递归/迭代处理子节点即可。

通用递归遍历实现

适合绝大多数常规场景,遍历过程中会输出每个节点的JSONPath路径、类型和值,方便定位:

/// <summary>
/// 深度优先遍历JSON树
/// </summary>
/// <param name="node">当前遍历节点</param>
/// <param name="parentPath">当前节点的父级JSONPath路径</param>
public static void TraverseJsonTree(JToken node, string parentPath = "$")
{
    switch (node.Type)
    {
        case JTokenType.Object:
            // 遍历对象下的所有属性
            foreach (JProperty prop in node.Children<JProperty>())
            {
                string currentPath = $"{parentPath}.{prop.Name}";
                Console.WriteLine($"[对象属性] 路径:{currentPath} | 属性名:{prop.Name} | 值类型:{prop.Value.Type}");
                TraverseJsonTree(prop.Value, currentPath);
            }
            break;
        case JTokenType.Array:
            // 遍历数组下的所有元素,记录索引
            int index = 0;
            foreach (JToken item in node.Children())
            {
                string currentPath = $"{parentPath}[{index}]";
                Console.WriteLine($"[数组元素] 路径:{currentPath} | 索引:{index} | 值类型:{item.Type}");
                TraverseJsonTree(item, currentPath);
                index++;
            }
            break;
        default:
            // 叶子节点,无下级子节点
            Console.WriteLine($"[叶子节点] 路径:{parentPath} | 值:{node}");
            break;
    }
}

调用方式:

// 解析JSON字符串,根为对象时可用JObject,不确定根类型时直接用JToken.Parse兼容所有场景
JToken root = JToken.Parse(待处理的JSON字符串内容);
TraverseJsonTree(root);

非递归遍历实现

如果要处理嵌套层级极深(超过1000层)的JSON,避免递归栈溢出,可以用栈实现迭代遍历,逻辑和递归一致:

public static void TraverseJsonTreeWithoutRecursion(JToken root)
{
    Stack<(JToken Node, string Path)> traverseStack = new Stack<(JToken, string)>();
    traverseStack.Push((root, "$"));

    while (traverseStack.Count > 0)
    {
        var (currentNode, currentPath) = traverseStack.Pop();
        if (currentNode is JObject obj)
        {
            // Reverse是为了保证遍历顺序和递归逻辑一致,不需要顺序一致可以去掉
            foreach (JProperty prop in obj.Properties().Reverse())
            {
                traverseStack.Push((prop.Value, $"{currentPath}.{prop.Name}"));
            }
        }
        else if (currentNode is JArray arr)
        {
            for (int i = arr.Count - 1; i >= 0; i--)
            {
                traverseStack.Push((arr[i], $"{currentPath}[{i}]"));
            }
        }
        else
        {
            Console.WriteLine($"[叶子节点] 路径:{currentPath} | 值:{currentNode}");
        }
    }
}

统计JSON项数量

统计前先明确统计维度,常见的统计项包括叶子节点总数、对象属性总数、数组元素总数、对象/数组节点总数,直接基于遍历逻辑累加计数即可:

/// <summary>
/// JSON结构统计结果
/// </summary>
public class JsonCountResult
{
    /// <summary>叶子值节点总数</summary>
    public int LeafNodeCount { get; set; }
    /// <summary>对象节点总数</summary>
    public int ObjectCount { get; set; }
    /// <summary>对象属性总数</summary>
    public int PropertyCount { get; set; }
    /// <summary>数组节点总数</summary>
    public int ArrayCount { get; set; }
    /// <summary>数组元素总数</summary>
    public int ArrayItemCount { get; set; }
}

public static JsonCountResult CountJsonItems(JToken root)
{
    JsonCountResult result = new JsonCountResult();
    Stack<JToken> stack = new Stack<JToken>();
    stack.Push(root);

    while (stack.Count > 0)
    {
        JToken current = stack.Pop();
        switch (current.Type)
        {
            case JTokenType.Object:
                result.ObjectCount++;
                foreach (JProperty prop in current.Children<JProperty>())
                {
                    result.PropertyCount++;
                    stack.Push(prop.Value);
                }
                break;
            case JTokenType.Array:
                result.ArrayCount++;
                foreach (JToken item in current.Children())
                {
                    result.ArrayItemCount++;
                    stack.Push(item);
                }
                break;
            default:
                result.LeafNodeCount++;
                break;
        }
    }
    return result;
}

注意事项

  • 如果JSON根节点是数组,不要用JObject.Parse解析,直接用JToken.Parse可以兼容根为对象、数组、单值的所有场景
  • 如果只是查找特定名称/特定值的节点,遍历到目标节点后可以直接终止遍历,不需要走完整个树,性能更好
  • 对于大小超过100MB的超大JSON文件,不建议直接加载为JObject全量遍历,应该用流式读取的方式处理,避免内存占用过高

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 02:27:30