ツリー構造を含む DataTable があります。それを、ExtJS ツリーにバインドできる JSON オブジェクトに変換したいと考えています。DataTable をツリー構造に変換することはできますが (Stackoverflow ユーザーの 1 人に感謝します)、JSON に変換することはできません。EXTJs ツリーにバインドできるはずの JSON オブジェクトを返したいです。
**これはやりたくない: string json = JsonConvert.SerializeObject(table, Formatting.Indented);
これは DataTable を JSON に変換するだけですが、親子関係は維持されません。**
これが私のコードです。
public class Node<T>
{
public T Item { get; internal set; }
public int Level { get; internal set; }
public Node<T> Parent { get; internal set; }
public IList<Node<T>> Children { get; internal set; }
}
public static class Program
{
private static void Main(string[] args)
{
DataTable table = new DataTable();
table.Columns.Add("name", typeof(string));
table.Columns.Add("key", typeof (string));
table.Columns.Add("parentkey", typeof (string));
table.Columns.Add("Level", typeof (int));
table.Rows.Add("A", "A1", null, 1);
table.Rows.Add("B", "A2", "A1", 2);
table.Rows.Add("C", "A3", "A1", 2);
table.Rows.Add("D", "A4", "A1", 2);
table.Rows.Add("E", "A5", "A2", 3);
table.Rows.Add("F", "A6", "A5", 4);
table.Rows.Add("G", "A7", "A3", 3);
table.Rows.Add("H", "A8", "A4", 3);
table.Rows.Add("I", "A9", "A4", 3);
table.Rows.Add("J", "A10", "A4", 3);
table.Rows.Add("K", "A11", "A10", 4);
table.Rows.Add("L", "A12", "A10", 4);
table.Rows.Add("M", "A13", "A12", 5);
table.Rows.Add("N", "A14", "A12", 5);
table.Rows.Add("O", "A15", "A10", 4);
table.Rows.Add("P", "A16", null, 1);
table.Rows.Add("Q", "A17", "A16", 2);
DataView view = table.DefaultView;
// By default, the first column sorted ascending.
view.Sort = "Level, ParentKey DESC";
var hierarchy =
table.AsEnumerable()
.ToHierarchy(row => row.IsNull("parentkey"),
(parent, child) => parent.Field<string>("key") ==
child.Field<string>("parentkey"));
//HOW TO CONVERT THIS HIERARCHY INTO JSON???
Console.ReadKey();
}
public static IEnumerable<Node<T>> ToHierarchy<T>(this IEnumerable<T> source,Func<T, bool> startWith, Func<T, T, bool> connectBy)
{
if (source == null) throw new ArgumentNullException("source");
if (startWith == null) throw new ArgumentNullException("startWith");
if (connectBy == null) throw new ArgumentNullException("connectBy");
return source.ToHierarchy(startWith, connectBy, null);
}
private static IEnumerable<Node<T>> ToHierarchy<T>(this IEnumerable<T> source,Func<T, bool> startWith,Func<T, T, bool> connectBy,Node<T> parent)
{
int level = (parent == null ? 0 : parent.Level + 1);
var roots = from item in source
where startWith(item)
select item;
foreach (T value in roots)
{
var children = new List<Node<T>>();
var newNode = new Node<T>
{
Level = level,
Parent = parent,
Item = value,
Children = children.AsReadOnly()
};
T tmpValue = value;
children.AddRange(source.ToHierarchy(possibleSub => connectBy(tmpValue, possibleSub), connectBy, newNode));
yield return newNode;
}
}
}