C#父子ID的表数据转换成Tree型Json数据
在开发中有许多需要生成树型JSON数据的情况,比如侧边栏菜单、组织结构等,下面为两种JSON格式的数据生成方法。
public class Node { /// <summary> /// id /// </summary> public int id { get; set; } /// <summary> /// 上级id /// </summary> public int pid { get; set; } public string text { get; set; } }
[ { "id":1, "pid":0, "text":"节点1", "children":[ { "id":2, "pid":1, "text":"节点1->2", "children":[ { "id":4, "pid":2, "text":"节点1->2->4", "children":[] }, { "id":5, "pid":2, "text":"节点1->2->5", "children":[] } ] }, { "id":3, "pid":1, "text":"节点1->3", "children":[ ] } ] }, { "id":6, "pid":0, "text":"节点6", "children":[ { "id":7, "pid":6, "text":"节点6->7", "children":[ { "id":8, "pid":7, "text":"节点6->7->8", "children":[] } ] } ] } ]
使用泛型,通过反射生成
IEnumerable<object>
对象,再进行序列化
(1). 实现
///泛型K为pid的数据类型 public static IEnumerable<object> GetChildrenTreeNode<T, K>(IEnumerable<T> notes, Func<T, K> idSelector, Func<T, K> parentIdSelector, K rootId = default(K)) where T : class { var dView = notes.Where(x => { K pid = parentIdSelector(x); return (rootId == null && pid == null) || (rootId != null && pid.Equals(rootId)); }); // List<Object> objList = new List<object>(); foreach (var dr in dView) { var testType = typeof(T); var propertyInfos = testType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); //******************获取源对象数据****************// Dictionary<string, object> dicObj = new Dictionary<string, object>(); foreach (var property in propertyInfos) { var value = property?.GetValue(dr); if (value != null) { dicObj.Add(property.Name, value); } } var children = GetChildrenTreeNode(notes, idSelector, parentIdSelector, idSelector(dr)); dicObj.Add("children", children); //objList.Add(dicObj); yield return dicObj; } // return objList; }
先定义类
NoteView
,返回IEnumerable<NodeView>
,再进行序列化
(1). 定义NoteView
public class NodeView { public int id { get; set; } public int pid { get; set; } public string text { get; set; } public IEnumerable<NodeView> children { get; set; } }
(2). 实现
///pid为最顶级note的id private IEnumerable<NodeView> GetChildrenTreeNode(IEnumerable<Node> notes, int pid = 0) { var noteList = notes.Where(x => { return pid.Equals(x.pid); }); //List<NodeView> noteViews = new List<NodeView>(); foreach (var note in noteList) { var view = new NodeView(); view.id = note.id; view.pid = note.pid; view.text = note.text; view.children = GetChildrenTreeNode(notes, note.id); //noteViews.Add(view); yield return view; } // return noteViews; }
List<Node> notes = new List<Node>(); notes.Add(new Node { id = 1, pid = 0, text = "节点1" }); notes.Add(new Node { id = 2, pid = 1, text = "节点1->2" }); notes.Add(new Node { id = 3, pid = 1, text = "节点1->3" }); notes.Add(new Node { id = 4, pid = 2, text = "节点1->2->4" }); notes.Add(new Node { id = 5, pid = 2, text = "节点1->2->5" }); notes.Add(new Node { id = 6, pid = 0, text = "节点6" }); notes.Add(new Node { id = 7, pid = 6, text = "节点6->7" }); notes.Add(new Node { id = 8, pid = 7, text = "节点6->7->8" }); //dt.Add(new Node { id = 9, pid = 1, text = "节点1->9" }); //方案一 var treeNotes1 = GetChildrenTreeNode(notes, x => x.id, y => y.pid); string jsonStr1 = Newtonsoft.Json.JsonConvert.SerializeObject(treeNotes1); Console.WriteLine(jsonStr1); //方案二 var treeNotes2 = GetChildrenTreeNode(notes); string jsonStr2 = Newtonsoft.Json.JsonConvert.SerializeObject(treeNotes2); Console.WriteLine(jsonStr2);
和前一种数据的格式不同
[ { "Item": { "id": 1, "pid": 0, "text": "节点1" }, "Children": [ { "Item": { "id": 2, "pid": 1, "text": "节点1->2" }, "Children": [ { "Item": { "id": 4, "pid": 2, "text": "节点1->2->4" }, "Children": [] }, { "Item": { "id": 5, "pid": 2, "text": "节点1->2->5" }, "Children": [] } ] }, { "Item": { "id": 3, "pid": 1, "text": "节点1->3" }, "Children": [] } ] }, { "Item": { "id": 6, "pid": 0, "text": "节点6" }, "Children": [ { "Item": { "id": 7, "pid": 6, "text": "节点6->7" }, "Children": [ { "Item": { "id": 8, "pid": 7, "text": "节点6->7->8" }, "Children": [] } ] } ] } ]
(1). TreeItem定义
public class TreeItem<T> { public T Item { get; set; } public IEnumerable<TreeItem<T>> Children { get; set; } }
(2). 实现
public static IEnumerable<TreeItem<T>> GetChildrenTreeNode<T, K>(IEnumerable<T> notes, Func<T, K> idSelector, Func<T, K> parentIdSelector, K rootId = default(K)) { foreach (var c in notes.Where(u => { var selector = parentIdSelector(u); return (rootId == null && selector == null) || (rootId != null && rootId.Equals(selector)); })) { yield return new TreeItem<T> { Item = c, Children = GetChildrenTreeNode(notes, idSelector, parentIdSelector, idSelector(c)) }; } }
示例中
notes
的数据初始化同上
//... //`notes`的数据初始化同上 var treeNotes3 = GetChildrenTreeNode2(notes, x => x.id, y => y.pid); string jsonStr3 = Newtonsoft.Json.JsonConvert.SerializeObject(treeNotes3); Console.WriteLine(jsonStr3);