我正在制作一个Web服务,它将以JSON格式给出响应。我已经从SQL Server提取了数据并将其存储在Datatable中。 dt的外观如下:-
id Caption pid
F182 GLOBAL REPORTS NULL
F184 software NULL
F1227 LYB P&L Reports F184
F1245 LYB Training F184
F1239 test3 F182
F1249 Paavan_Test_Reports F184
标题栏中pid为 Null 的项是父项,并且其子项与各自父级的 id 具有相同的 pid 。
例如: GLOBAL REPORTS 有1个孩子,即 test3 和软件有3个孩子。
我希望JSON响应采用以下格式
[{
id='F182',
caption='GLOBAL REPORTS',
pid=null;
items:[{
id='F1239',
caption='test3',
pid='F182'}]
},
{
id='F184',
caption='software',
pid='NULL',
items:[{
id='F1227',
caption='LYB P&L Reports',
pid='F184'
},
{
id='F1245',
caption='LYB Training',
pid='F184'
},
{
id='F1249',
caption='Paavan_Test_Reports',
pid='F184'
}
}]
我已经制作了一个类文件夹
class folder
{
string id{get;set;}
string pid{get;set;}
string caption{get;set;}
}
如何获取对象数组项,其中将包含特定父级的所有可用子级?我是Json对象和响应的新手,
我尝试使用以下方法:
var obj = dt.AsEnumerable()
.GroupBy(r => r["pid"])
.ToDictionary(g => g.Key.ToString(),
g => g.Select(r => new {
item = r["caption"].ToString(),
}).ToArray());
var json = JsonConvert.SerializeObject(obj);
但这给了我一个简单的json响应,没有任何层次。
答案 0 :(得分:3)
您需要在序列化之前构建对象层次结构。为此,请在您的folder
类中定义一个新属性:
public IEnumerable<folder> items { get; set; }
现在,您可以递归搜索每个根folder
的子对象:
public static IEnumerable<folder> BuildTree(folder current, folder[] allItems)
{
var childs = allItems.Where(c => c.pid == current.id).ToArray();
foreach (var child in childs)
child.items = BuildTree(child, allItems);
current.items = childs;
return childs;
}
用法:
var input = new[] // dt.AsEnumerable() in your case
{
new folder {id = "F182", caption = "GLOBAL REPORTS", pid = null },
new folder {id = "F184", caption = "software", pid = null },
new folder {id = "F1227", caption = "LYB P&L Reports", pid = "F184" },
new folder {id = "F1245", caption = "LYB Training", pid = "F184" },
new folder {id = "F1239", caption = "test3", pid = "F182" },
new folder {id = "F1249", caption = "Paavan_Test_Reports", pid = "F184" },
};
var roots = input.Where(i => i.pid == null);
foreach (var root in roots)
BuildTree(root, input);
var json = JsonConvert.SerializeObject(roots, Formatting.Indented);
此外,如果您想隐藏空的items
,则可以在ShouldSerialize
类中定义方法folder
:
public bool ShouldSerializeitems()
{
return items.Any();
}
演示是here
答案 1 :(得分:2)
我认为您想要的是在文件夹中包含一个文件夹列表,如下所示:
class folder
{
string id{get;set;}
string pid{get;set;}
string caption{get;set;}
List<folder> items {get;set;}
}
在这种情况下使用JSONConvert时,如果在子级集合中存在父级,则可能会遇到循环依赖项。您可以使用SerializerSettings对象忽略这些情况,对于项列表中的子项,可以将其集合设置为null,这样就不会序列化。
但是,您指定的所需输出也会列出文件夹的数组。因此,最后,您需要序列化文件夹类的集合(例如,列表或数组)。像
关于如何加载数据,我想您已经加载了具有id,pid和caption的文件夹,但是items属性为空。
为了建立父子关系,您可以这样
var folders = dt.AsEnumerable().ToList();
foreach(var folder in folders) {
folder.items = folders.Where(f => f.pid.Equals(folder.id)).ToList();
}
var parentFolders = folders.Where(f => f.pid is null);
var json = JsonConvert.SerializeObject(parentFolders, new SerializerSettings () {
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});