![](/img/trans.png)
[英]Deserializing a JSON object hierarchy into a hierarchy of Dictionary<string, object>
[英]JSON to a custom object hierarchy
我有一些 JSON,它由一組具有 ID 和名稱的對象組成,還有另一個 object 給出了父對象的 ID 和名稱。 它本質上是一個文件夾結構,所以根文件夾會有子文件夾,它們也會有子文件夾等。
{
"data": [
{
"id": 66880231, //unique
"name": "root", //not unique
"parent": null
},
{
"id": 68102146,
"name": "Dummy",
"parent": {
"id": 66880231,
"name": "root"
}
},
{
"id": 68509957,
"name": "Test - Dummy",
"parent": {
"id": 68102146,
"name": "Dummy"
}
},
{
"id": 68509998,
"name": "Another Folder",
"parent": {
"id": 68102146,
"name": "Dummy"
}
}
]
}
我將其反序列化為一個名為 ClioFolders 的ClioFolders
。
接下來,我需要遍歷每個ClioFolders
對象並將它們放入一個名為AllClioFolders
的新 object 中,但它不會列出父級,而是成為父級的子 object。 我假設List
是這樣做的方法,但我不確定。
這是自定義 object 的 class:
public class AllClioFolders
{
public string Id { get; set; }
public string Name { get; set; }
public List<AllClioFolders> Children { get; set; }
}
實際上,我將擁有 18,000 多個對象,而且它們不一定是有序的。 每個都需要作為子 object 添加到其父級。
我能想到的最好的解釋方式是展示它在 JSON 中的樣子:
{
"id": 66880231,
"name": "root",
"children": [
{
"id": 68102146,
"name": "Dummy",
"children": [
{
"id": 68509957,
"name": "Test - Dummy",
"children": []
},
{
"id": 68509998,
"name": "Another Folder",
"children": []
}
]
}
]
}
我面臨的問題是我無法弄清楚如何將 object 添加到相關的父 object 中。 我幾乎可以肯定需要使用 LINQ,但這超出了我的 c# 知識。 任何幫助將不勝感激。
foreach(var folder in GetFolders.Data)
{
if(folder.Parent == null)
{
//Root object
AllClioFolders.Add(new AllClioFolders { Name = folder.Name, Id = folder.Id.ToString() });
}
else
{
//Child Object
//Add this object to the correct parent object
// AllClioFolders.Add(????);
}
}
更新:我懷疑這樣的事情應該可以工作,但它只會添加到頂級對象的子 object,它需要能夠查看所有子對象。
var obj = AllClioFolders.FirstOrDefault(x => x.Id == folder.Parent.ToString());
if (obj != null) obj.Children.Add(new AllClioFolders { Name = folder.Name, Id = folder.Id.ToString() });
我認為答案取決於。 取決於你想獲得什么。
您在示例 json 中顯示的內容只不過是一個樹結構。
您有第一個 json 但相反(您有指向父級的指針,而不是將它們指向子級),因為父級只有一個。
因此,如果您想在 object 中重現樹結構,您已經足夠接近,您只需要使用遞歸即可。
AllClioFolders rootClioFolder;
List<AllClioFolders> orphans;
foreach(var folder in GetFolders.Data)
{
AllClioFolders currentFolder=new AllClioFolders { Name = folder.Name, Id = folder.Id.ToString() };
if(folder.Parent == null)
{
//Root object
rootClioFolder=currentFolder;
}
else
{
AllClioFolders parentFolder=findParent(currentFolder.Id,rootClioFolder);
if (parentFolder!=null){
parentFolder.Children.Add(currentFolder);
}else{
orphans.Add(currentFolder)
}
}
}
function AllClioFolders findParent(string Id,AllClioFolders treeFolder){
AllClioFolders resultFolder=null;
if (currentFolder.Id==Id){
resultFolder=treeFolder;
}else{
foreach (AllClioFolders children in treeFolder.Children){
resultFolder=findParent(Id,children);
if (resultFolder!=null) break;
}
}
return resultFolder;
}
筆記:
但是,我建議更改 class 並僅使用Dictionary<string,AllClioFolders>
,其中 Id 是鍵,因此您可以簡單地通過 id 直接訪問並且可以迭代。
編輯:我注意到我讀錯了,ID 是增量的,如果是這種情況,那么你只需要做GetFolders.Data.OrderBy(function (folder) folder.Id)
我已經嘗試過這種方法並且效果很好。
按父 id對所有子進行分組,並遞歸填充每個parent
的所有children
:
1 - 類:
請注意,我已將AllClioFolders
中的Id
類型更改為Int
public class RootObject
{
public List<ClioFolder> Data { get; set; }
}
public class Parent
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ClioFolder
{
public int Id { get; set; }
public string Name { get; set; }
public Parent Parent { get; set; }
}
public class AllClioFolders
{
public int Id { get; set; }
public string Name { get; set; }
public List<AllClioFolders> Children { get; set; }
}
2 - Json
string json = @"{
'data': [
{
'id': 66880231,
'name': 'root',
'parent': null
},
{
'id': 68102146,
'name': 'Dummy',
'parent': {
'id': 66880231,
'name': 'root'
}
},
{
'id': 68509957,
'name': 'Test - Dummy',
'parent': {
'id': 68102146,
'name': 'Dummy'
}
},
{
'id': 68509998,
'name': 'Another Folder',
'parent': {
'id': 68102146,
'name': 'Dummy'
}
}
]
}";
3 - json 反序列化,構造父級並按父級 ID 對子級進行分組:
List<ClioFolder> allClios = JsonConvert.DeserializeObject<RootObject>(json)?.Data;
//get parent
ClioFolder clioFolder = allClios.FirstOrDefault(c => c.Parent == null);
AllClioFolders allClioParent = new AllClioFolders
{
Id = clioFolder.Id,
Name = clioFolder.Name,
Children = new List<AllClioFolders>()
};
// group by parent id
Dictionary<int, List<ClioFolder>> groupedChilds = allClios
.Where(c => c.Parent != null)
.GroupBy(c => c.Parent.Id)
.ToDictionary(k => k.Key, v => v.ToList());
AddChildrenRecursively(groupedChilds, allClioParent);
string result = JsonConvert.SerializeObject(allClioParent);
Console.WriteLine(result);
4 - 方法的實施
static void AddChildrenRecursively(Dictionary<int, List<ClioFolder>> groupeChilds, AllClioFolders allClioParent)
{
if (groupeChilds.ContainsKey(allClioParent.Id))
{
allClioParent.Children = groupeChilds[allClioParent.Id].Select(x => new AllClioFolders { Id = x.Id, Name = x.Name }).ToList();
foreach (AllClioFolders childOfChild in allClioParent.Children)
{
AddChildrenRecursively(groupeChilds, childOfChild);
}
}
}
結果
{
"Id":66880231,
"Name":"root",
"Children":[
{
"Id":68102146,
"Name":"Dummy",
"Children":[
{
"Id":68509957,
"Name":"Test - Dummy",
"Children":null
},
{
"Id":68509998,
"Name":"Another Folder",
"Children":null
}
]
}
]
}
我希望你覺得這有幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.