C#父子ID的表數據轉換成Tree型Json數據
在開發中有許多需要生成樹型JSON數據的情況,比如側邊欄菜單、組織結構等,下面為兩種JSON格式的數據生成方法。
1.現在有這樣字段的父子結構的表
public class Node
{
/// <summary>
/// id
/// </summary>
public int id { get; set; }
/// <summary>
/// 上級id
/// </summary>
public int pid { get; set; }
public string text { get; set; }
}
2.生成第一種格式的樹型JSON字符串:
- JSON數據
[
{
"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);
3.生成第二種格式的樹型JSON字符串:
- JSON數據
和前一種數據的格式不同
[
{
"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);