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

如何用Newtonsoft.Json提取含指定键的JSON子树及所有父节点?

实现JToken中按关键字提取含目标键及父节点的子JSON

完全可以实现这个需求,核心思路是先定位所有包含目标键的节点,再回溯保留它们的父节点路径,最后根据这些路径构建出过滤后的JSON结构。

具体实现步骤

  1. 遍历JToken收集目标键的完整路径:递归遍历整个JToken结构,记录每个目标键从根节点到自身的层级路径。
  2. 根据路径构建结果JSON:按照收集到的路径,逐个将路径上的节点复制到结果对象中,只保留能关联到目标键的分支。

C#代码示例

1. 收集所有目标键的路径

private static List<List<string>> FindAllPaths(JToken root, string targetKey)
{
    var paths = new List<List<string>>();
    Traverse(root, new List<string>(), targetKey, paths);
    return paths;
}

private static void Traverse(JToken token, List<string> currentPath, string targetKey, List<List<string>> paths)
{
    if (token is JObject obj)
    {
        foreach (var prop in obj.Properties())
        {
            var newPath = new List<string>(currentPath) { prop.Name };
            if (prop.Name == targetKey)
            {
                paths.Add(newPath);
            }
            Traverse(prop.Value, newPath, targetKey, paths);
        }
    }
    // 如需处理数组,可添加JArray的遍历逻辑
    else if (token is JArray array)
    {
        for (int i = 0; i < array.Count; i++)
        {
            var newPath = new List<string>(currentPath) { $"[{i}]" };
            Traverse(array[i], newPath, targetKey, paths);
        }
    }
}

2. 根据路径构建结果对象

private static JToken BuildResultFromPaths(JToken root, List<List<string>> paths)
{
    var result = new JObject();
    foreach (var path in paths)
    {
        JToken currentOriginal = root;
        JToken currentResult = result;
        
        for (int i = 0; i < path.Count; i++)
        {
            var key = path[i];
            if (currentOriginal is JObject originalObj)
            {
                var prop = originalObj.Property(key);
                if (prop == null) continue;

                if (currentResult is JObject resultObj)
                {
                    if (!resultObj.ContainsKey(key))
                    {
                        // 最后一层是目标键,直接复制属性;否则创建空容器继续深入
                        if (i == path.Count - 1)
                        {
                            resultObj.Add(prop.Name, prop.Value.DeepClone());
                        }
                        else
                        {
                            var newContainer = new JObject();
                            resultObj.Add(prop.Name, newContainer);
                            currentResult = newContainer;
                        }
                    }
                    else
                    {
                        // 父节点已存在,直接进入下一层
                        currentResult = resultObj[key];
                    }
                }
                currentOriginal = prop.Value;
            }
            // 如需处理数组,可添加对应逻辑
        }
    }
    return result;
}

3. 使用示例

// 解析原JSON为JToken
var originalJson = @"
{
    ""Name"": ""Torr"",
    ""Attr1"": {
        ""A"": 1,
        ""Attr1_1"": {
            ""A"": 1
        },
        ""Attr1_2"" :{
            ""B"": 1
        }
    },
    ""A"": 2
}";
var root = JToken.Parse(originalJson);

// 搜索目标键"A"
var targetKey = "A";
var paths = FindAllPaths(root, targetKey);
var filteredResult = BuildResultFromPaths(root, paths);

// 输出格式化后的结果
Console.WriteLine(filteredResult.ToString(Newtonsoft.Json.Formatting.Indented));

代码说明

  • 递归遍历能覆盖所有嵌套层级,确保不会遗漏任何目标键的位置
  • 使用DeepClone()避免修改原JToken对象,保证数据独立性
  • 可以扩展JArray的处理逻辑,适配包含数组的JSON结构

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 23:18:25