繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM