C# 如何从平面(“非规范化”)数组构造嵌套的强类型对象?

C# 如何从平面(“非规范化”)数组构造嵌套的强类型对象?,c#,arrays,.net,json,linq,C#,Arrays,.net,Json,Linq,我正在编写一个.NET服务来从包含数据的web服务中使用(获取)JSON数组,如果在数据库中,这些数据将被规范化为单独的相关表。JSON数组中的每个元素都会重复父数据属性,只有子元素的属性会随着元素的变化而变化。下面是JSON对象的外观: [ { "parentID": 123, "parentName": "Parent Name", "childID": 1, "childName": "First Child", "subChildID": nul

我正在编写一个.NET服务来从包含数据的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; }
        }
    }
}
公共类ParentObject
{
public int parentID{get;set;}
公共字符串parentName{get;set;}
公共列表子项{get;set;}
私有类子对象
{
public int childID{get;set;}
公共字符串childName{get;set;}
公共列表子项{get;set;}
私有类子对象
{
public int subchilded{get;set;}
公共字符串子子名{get;set;}
}
}
}
我看到过相反的例子;将嵌套对象展平为类似列表的对象,但不是我要查找的对象。我再次希望它可以通过Newtonsoft或plain Linq的Json库实现。谢谢。

我相信这可以用Linq实现,但只需一个循环就可以轻松实现,如下面的示例代码所示:

列出CreateEntities(字符串json)
{
var entities=JsonConvert.DeserializeObject(json);
列表父项=新列表();
foreach(实体中的var实体)
{
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(新建ParentObject.ChildObject.SubChildObject
{
subChildID=entity.subChildID.Value,
subChildName=entity.subChildName
});
}
}
其他的
{
var newChild=(新的ParentObject.ChildObject
{
childID=entity.childID,
childName=entity.childName,
子项=新列表()
});
if(entity.subChildID.HasValue)
{
newChild.subChildren.Add(newparentobject.ChildObject.SubChildObject
{
subChildID=entity.subChildID.Value,
subChildName=entity.subChildName
});
}
parent.children.Add(newChild);
}
}
其他的
{
var newParent=newparentobject
{
parentID=entity.parentID,
parentName=entity.parentName,
儿童=新列表
{
新建ParentObject.ChildObject
{
childID=entity.childID,
childName=entity.childName,
子项=新列表()
}
}
};
if(entity.subChildID.HasValue)
{
newParent.children.Single().subChildren.Add(new ParentObject.ChildObject.SubChildObject
{
subChildID=entity.subChildID.Value,
subChildName=entity.subChildName
});
}
parents.Add(newParent);
}
}
返回父母;
}
公共类根对象
{
public int parentID{get;set;}
公共字符串parentName{get;set;}
public int childID{get;set;}
公共字符串childName{get;set;}
public int?subchilded{get;set;}
公共字符串子子名{get;set;}
}
公共类父对象
{
public int parentID{get;set;}
公共字符串parentName{get;set;}
公共列表子项{get;set;}
公共类子对象
{
public int childID{get;set;}
公共字符串childName{get;set;}
公共列表子项{get;set;}
公共类次儿童项目
{
public int subchilded{get;set;}
公共字符串子子名{get;set;}
}
}
}
输出:

注:


这段代码在一个响应中处理多个父项,尽管您的问题表明每个响应只有一个父项,但我不完全确定。

您尝试过什么吗?如果是,哪里出了问题?(错误、意外结果等)我试着写了一些Linq GroupBy语句,但我对这些语句没有很好的把握,所以它什么都没做。很好,谢谢。是的,在我进入循环/递归兔洞之前,我想问一下是否有更有效的方法来实现它。似乎应该有,对吧?我会让你的代码转一转,然后再回来……也许有一种更简洁的方法可以做到这一点,但我认为没有更有效的方法——在一天结束时,你必须遍历实体来取消它们的框架,这只会迭代它们一次。你的代码完成了这项工作。是的,使用其他Linq语句可能更有效,但这不适用于大型对象,因此您的算法可以工作。谢谢