[英]How do I construct a nested, strongly typed object from a flat ("non-normalized") array?
我正在编写一个 .NET 服务来使用(GET)来自包含数据的 Web 服务的 JSON 数组,如果在数据库中,这些数据将被规范化为单独的相关表。 JSON 数组将与每个重复父数据属性的元素一起出现,并且只有子元素的属性会从元素到元素发生变化。 所以这里是 JSON 对象的样子:
[ {
"parentID": 123,
"parentName": "Parent Name",
"childID": 1,
"childName": "First Child",
"subChildID": null,
"subChildName": null
},
{
"parentID": 123,
"parentName": "Parent Name",
"childID": 2,
"childName": "Second Child",
"subChildID": null,
"subChildName": null
},
{
"parentID": 123,
"parentName": "Parent Name",
"childID": 3,
"childName": "Third Child",
"subChildID": 100,
"subChildName": "First Subchild of the third child"
},
{
"parentID": 123,
"parentName": "Parent Name",
"childID": 4,
"childName": "Third child",
"subChildID": 101,
"subChildName": "Second subchild of the third child"
}]
但是我需要将这个数组(希望使用 Newtonsoft 或 Linq 库?)转换为一个 .NET 对象,它看起来像这样:
public class ParentObject
{
public int parentID { get; set; }
public string parentName { get; set; }
public List<ChildObject> children { get; set; }
private class ChildObject
{
public int childID { get; set; }
public string childName { get; set; }
public List<SubChildObject> subChildren { get; set; }
private class SubChildObject
{
public int subChildID { get; set; }
public string subChildName { get; set; }
}
}
}
我见过相反的例子; 将嵌套对象展平为类似列表的对象,但不是我要找的。 再次,我希望它可以通过 Newtonsoft 或普通 Linq 的 Json 库来完成。 谢谢。
我敢肯定,这可以用Linq完成,但是只需循环就可以轻松实现,如下面的示例代码所示:
List<ParentObject> CreateEntities(string json)
{
var entities = JsonConvert.DeserializeObject<List<RootObject>>(json);
List<ParentObject> parents = new List<ParentObject>();
foreach (var entity in entities)
{
if (parents.Any(p => p.parentID == entity.parentID))
{
var parent = parents.Single(p => p.parentID == entity.parentID);
if (parent.children.Any(c => c.childID == entity.childID))
{
var child = parent.children.Single(c => c.childID == entity.childID);
if (entity.subChildID.HasValue)
{
child.subChildren.Add(new ParentObject.ChildObject.SubChildObject
{
subChildID = entity.subChildID.Value,
subChildName = entity.subChildName
});
}
}
else
{
var newChild = (new ParentObject.ChildObject
{
childID = entity.childID,
childName = entity.childName,
subChildren = new List<ParentObject.ChildObject.SubChildObject>()
});
if (entity.subChildID.HasValue)
{
newChild.subChildren.Add(new ParentObject.ChildObject.SubChildObject
{
subChildID = entity.subChildID.Value,
subChildName = entity.subChildName
});
}
parent.children.Add(newChild);
}
}
else
{
var newParent = new ParentObject
{
parentID = entity.parentID,
parentName = entity.parentName,
children = new List<ParentObject.ChildObject>
{
new ParentObject.ChildObject
{
childID = entity.childID,
childName = entity.childName,
subChildren = new List<ParentObject.ChildObject.SubChildObject>()
}
}
};
if (entity.subChildID.HasValue)
{
newParent.children.Single().subChildren.Add(new ParentObject.ChildObject.SubChildObject
{
subChildID = entity.subChildID.Value,
subChildName = entity.subChildName
});
}
parents.Add(newParent);
}
}
return parents;
}
public class RootObject
{
public int parentID { get; set; }
public string parentName { get; set; }
public int childID { get; set; }
public string childName { get; set; }
public int? subChildID { get; set; }
public string subChildName { get; set; }
}
public class ParentObject
{
public int parentID { get; set; }
public string parentName { get; set; }
public List<ChildObject> children { get; set; }
public class ChildObject
{
public int childID { get; set; }
public string childName { get; set; }
public List<SubChildObject> subChildren { get; set; }
public class SubChildObject
{
public int subChildID { get; set; }
public string subChildName { get; set; }
}
}
}
输出:
注意:
这段代码可以在一个响应中处理多个父母,就像您的问题表明我不确定每个响应只有一个父母一样。
JSON中的两个“ Third childs”对象都具有不同的名称“ Third child”和“ Third C hild”,并具有不同的ID 3和4,我将这些字段设置为相同,以获得更好的输出结果。
我也用int?
ID,因为JSON具有可为null的int字段和Tuples (C#7.0)而不是匿名对象。
您可以删除Where
的过滤器,以收集与无效的ID也对象。
如果您有任何疑问或需要修复,请告诉我,这是代码:
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
internal class Program
{
private static void Main(string[] args)
{
string json = @"[
{
""parentID"": 123,
""parentName"": ""Parent Name"",
""childID"": 1,
""childName"": ""First Child"",
""subChildID"": null,
""subChildName"": null
},
{
""parentID"": 123,
""parentName"": ""Parent Name"",
""childID"": 2,
""childName"": ""Second Child"",
""subChildID"": null,
""subChildName"": null
},
{
""parentID"": 123,
""parentName"": ""Parent Name"",
""childID"": 3,
""childName"": ""Third child"",
""subChildID"": 100,
""subChildName"": ""First Subchild of the third child""
},
{
""parentID"": 123,
""parentName"": ""Parent Name"",
""childID"": 3,
""childName"": ""Third child"",
""subChildID"": 101,
""subChildName"": ""Second subchild of the third child""
}
]";
JArray jarr = JArray.Parse(json);
IEnumerable<ParentObject> parents = jarr.GroupBy(t => ((int?)t["parentID"], (string)t["parentName"]))
.Select(pg => new ParentObject
{
parentID = pg.Key.Item1,
parentName = pg.Key.Item2,
children = pg
.GroupBy(t => ((int?)t["childID"], (string)t["childName"]))
.Select(cg => new ParentObject.ChildObject()
{
childID = cg.Key.Item1,
childName = cg.Key.Item2,
subChildren = cg
.Select(t => new ParentObject.ChildObject.SubChildObject()
{
subChildID = (int?)t["subChildID"],
subChildName = (string)t["subChildName"]
}).Where(s => s.subChildID != null).ToList()
}).Where(c => c.childID != null).ToList()
}).Where(p => p.parentID != null).ToList();
json = JsonConvert.SerializeObject(parents, Formatting.Indented);
Console.WriteLine(json);
Console.ReadKey();
}
}
public class ParentObject
{
public int? parentID { get; set; }
public string parentName { get; set; }
public List<ChildObject> children { get; set; }
public class ChildObject
{
public int? childID { get; set; }
public string childName { get; set; }
public List<SubChildObject> subChildren { get; set; }
public class SubChildObject
{
public int? subChildID { get; set; }
public string subChildName { get; set; }
}
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.