如何在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
相关产品推荐
相关产品推荐

