如何在 c# 中创建嵌套的(父子)JSON 响应?

K. *_*jay 3 c# linq json visual-studio

我正在制作一个 Web 服务,它将以 JSON 格式提供响应。我已经从 sql server 获取数据并将其存储在数据表中。这就是 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
Run Code Online (Sandbox Code Playgroud)

标题列中 pid 为Null 的项目是父项,它们的子项的pid与其各自父项的id 相同

例如: 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'
    }
}]
Run Code Online (Sandbox Code Playgroud)

我已经创建了一个类文件夹

    class folder
    {
    string id{get;set;}
    string pid{get;set;}
    string caption{get;set;}
   }
Run Code Online (Sandbox Code Playgroud)

如何获取包含特定父项的所有可用子的对象数组?我是 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);
Run Code Online (Sandbox Code Playgroud)

但这给了我一个没有任何层次结构的简单 json 响应。

Ale*_*eev 6

您需要在序列化之前构建对象层次结构。为此,请在您的folder类中定义一个新属性:

public IEnumerable<folder> items { get; set; }
Run Code Online (Sandbox Code Playgroud)

现在您可以递归搜索每个根的孩子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;
}
Run Code Online (Sandbox Code Playgroud)

用法:

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);
Run Code Online (Sandbox Code Playgroud)

另外,如果你想隐藏空,items你可以ShouldSerializefolder类中定义方法:

public bool ShouldSerializeitems()
{
    return items.Any();
}
Run Code Online (Sandbox Code Playgroud)

演示在这里