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

如何在C#中动态生成层级JSON?基于GetChild方法实现

生成完整父子层级JSON结构的解决方案

嘿,这个问题其实很适合用递归来解决!你的GetChild目前只返回第一层级的子元素,我们只需要给每个子元素继续递归获取它们的子级,就能嵌套出完整的层级JSON了。下面分两种方案给你讲解:

方案一:直接递归调用现有方法(简单易实现)

这个方案基于你现有的ChildGet(id)方法,通过递归给每个子节点添加子级数据。

步骤1:扩展实体类(或修改原类)

首先,你的子元素实体类需要新增一个Children属性来存储子级数据。如果不能修改原实体类,可以创建一个继承它的扩展类:

// 假设你的原实体类是这样的
public class ChildItem {
    public long Id { get; set; }
    public long ParentId { get; set; }
    // 其他业务属性...
}

// 扩展类,添加Children属性用于层级嵌套
public class HierarchicalChildItem : ChildItem {
    public List<HierarchicalChildItem> Children { get; set; } = new List<HierarchicalChildItem>();
}

步骤2:编写递归构建方法

创建一个私有方法,负责递归获取并构建层级结构:

private List<HierarchicalChildItem> BuildFullHierarchy(long parentId) {
    Dal objDal = new Dal();
    // 获取当前父级的第一层级子元素,并转换为扩展类
    var firstLevelChildren = objDal.db.ChildGet(parentId)
                                     .Select(child => new HierarchicalChildItem {
                                         Id = child.Id,
                                         ParentId = child.ParentId,
                                         // 复制其他所有业务属性
                                         // 比如:Name = child.Name, Description = child.Description...
                                     }).ToList();

    // 递归给每个子元素添加自己的子级
    foreach (var child in firstLevelChildren) {
        child.Children = BuildFullHierarchy(child.Id);
    }

    return firstLevelChildren;
}

步骤3:修改原Action方法

把原来的GetChild方法改成调用递归方法:

public ActionResult GetChild(long id) {
    var fullHierarchy = BuildFullHierarchy(id);
    return Json(fullHierarchy, JsonRequestBehavior.AllowGet);
}

方案二:预加载所有数据再构建(性能优化)

如果你的数据量较大,方案一的多次数据库查询可能会影响性能。这时候可以先一次性查询所有层级的子元素,再在内存中构建层级:

步骤1:一次性获取所有相关数据

首先需要在Dal层实现一个方法,用SQL的CTE(公共表表达式)递归查询所有层级的子元素(或者用EF的递归查询):

// 假设Dal里新增这个方法,用CTE查询所有子元素
public List<ChildItem> GetAllChildItemsRecursively(long parentId) {
    // 示例SQL(根据你的数据库调整)
    string sql = @"
        WITH RecursiveChildren AS (
            SELECT * FROM ChildTable WHERE ParentId = @ParentId
            UNION ALL
            SELECT c.* FROM ChildTable c
            INNER JOIN RecursiveChildren rc ON c.ParentId = rc.Id
        )
        SELECT * FROM RecursiveChildren";
    
    return db.Database.SqlQuery<ChildItem>(sql, new SqlParameter("@ParentId", parentId)).ToList();
}

步骤2:内存中构建层级

用字典分组后递归构建,减少数据库访问次数:

public ActionResult GetChild(long id) {
    Dal objDal = new Dal();
    // 一次性获取所有层级的子元素
    var allChildItems = objDal.GetAllChildItemsRecursively(id).ToList();

    // 按ParentId分组,方便快速查找子元素
    var childGroupByParent = allChildItems.GroupBy(item => item.ParentId)
                                          .ToDictionary(group => group.Key, group => group.ToList());

    // 递归构建层级的本地方法
    List<ChildItem> BuildHierarchy(long currentParentId) {
        // 获取当前父级的所有子元素
        var children = childGroupByParent.TryGetValue(currentParentId, out var list) 
                        ? list 
                        : new List<ChildItem>();

        // 给每个子元素添加子级
        foreach (var child in children) {
            child.Children = BuildHierarchy(child.Id);
        }

        return children;
    }

    var fullHierarchy = BuildHierarchy(id);
    return Json(fullHierarchy, JsonRequestBehavior.AllowGet);
}

注意:这里需要给原ChildItem类添加Children属性:public List<ChildItem> Children { get; set; } = new List<ChildItem>();

额外注意事项

  • 循环引用问题:如果你的数据中存在父级引用子级、子级又引用父级的循环,需要在JSON序列化时配置忽略循环引用,比如在JsonRequestBehavior里或者全局配置ReferenceLoopHandling.Ignore。
  • 性能考量:数据量小的时候用方案一足够简单;数据量大的时候优先方案二,减少数据库IO。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:22:15