C# 解析嵌套分类JSON获取叶子节点ID及全层级分类路径方案
C# 嵌套分类全路径拼接实现方案
前置修正:调整实体类定义
你现有的SubCategory类中subCategories属性定义为List<object>会导致无法递归遍历子分类,需要修改为List<SubCategory>类型,修正后代码如下:
public class SubCategory { public int id { get; set; } public string name { get; set; } public int parentId { get; set; } // 修正类型为List<SubCategory>,支持多级嵌套遍历 public List<SubCategory> subCategories { get; set; } } public class Category { public int id { get; set; } public string name { get; set; } public object parentId { get; set; } public List<SubCategory> subCategories { get; set; } } public class Root { public List<Category> categories { get; set; } }
核心实现逻辑
通过递归遍历分类树,每进入一级分类就拼接当前分类名到路径中,当遇到subCategories为空的叶子节点时,记录当前节点ID和完整路径。
示例完整代码(以Newtonsoft.Json反序列化为例)
using System; using System.Collections.Generic; using Newtonsoft.Json; class Program { // 存储最终结果的结构 public class CategoryLeaf { public int Id { get; set; } public string FullPath { get; set; } } static void Main(string[] args) { // 你的JSON字符串 string jsonStr = @" { ""categories"": [ { ""id"": 368, ""name"": ""Accessory "", ""parentId"": null, ""subCategories"": [ { ""id"": 396, ""name"": ""Jewelery "", ""parentId"": 368, ""subCategories"": [ { ""id"": 397, ""name"": ""wristband"", ""parentId"": 396, ""subCategories"": [ { ""id"": 1238, ""name"": ""Gold wristband"", ""parentId"": 397, ""subCategories"": [] }, { ""id"": 1239, ""name"": ""Silver wristband"", ""parentId"": 397, ""subCategories"": [] }, { ""id"": 2845, ""name"": ""Steel wristband"", ""parentId"": 397, ""subCategories"": [] }, { ""id"": 3171, ""name"": ""Pearl wristband"", ""parentId"": 397, ""subCategories"": [] }, { ""id"": 3883, ""name"": ""diamond wristband"", ""parentId"": 397, ""subCategories"": [] } ] } ] } ] } ] }"; // 反序列化JSON Root root = JsonConvert.DeserializeObject<Root>(jsonStr); List<CategoryLeaf> result = new List<CategoryLeaf>(); // 遍历顶级分类 foreach (var topCate in root.categories) { // 初始路径为顶级分类名称,Trim掉多余空格 string initialPath = topCate.name.Trim(); // 递归遍历子分类 RecurseSubCate(topCate.subCategories, initialPath, result); } // 按要求格式输出 Console.WriteLine("Id - Name"); Console.WriteLine("-- ----------"); foreach (var leaf in result) { Console.WriteLine($"{leaf.Id} - {leaf.FullPath}"); } } /// <summary> /// 递归遍历子分类,收集叶子节点信息 /// </summary> /// <param name="subCates">当前层级分类列表</param> /// <param name="parentPath">上级分类拼接好的路径</param> /// <param name="result">结果收集集合</param> static void RecurseSubCate(List<SubCategory> subCates, string parentPath, List<CategoryLeaf> result) { if (subCates == null || subCates.Count == 0) return; foreach (var cate in subCates) { // 拼接当前分类到路径 string currentPath = $"{parentPath}>{cate.name.Trim()}"; // 判断是否为叶子节点(子分类为空) if (cate.subCategories == null || cate.subCategories.Count == 0) { result.Add(new CategoryLeaf { Id = cate.id, FullPath = currentPath }); } else { // 继续递归遍历下一级 RecurseSubCate(cate.subCategories, currentPath, result); } } } }
输出效果
Id - Name -- ---------- 1238 - Accessory>Jewelery>wristband>Gold wristband 1239 - Accessory>Jewelery>wristband>Silver wristband 2845 - Accessory>Jewelery>wristband>Steel wristband 3171 - Accessory>Jewelery>wristband>Pearl wristband 3883 - Accessory>Jewelery>wristband>diamond wristband
注意事项
- 如果使用System.Text.Json反序列化,只需要把
JsonConvert.DeserializeObject替换为JsonSerializer.Deserialize即可,逻辑无需改动 - 代码中对分类名称做了Trim处理,避免原JSON中名称前后的多余空格影响路径格式
内容的提问来源于stack exchange,提问作者Lvnt
相关产品推荐
相关产品推荐

