Linq-To-JSON走向祖先树为最近的父母获取JProperty

时间:2016-10-28 14:04:37

标签: c# json json.net linq-to-json

我有一个小提琴: https://dotnetfiddle.net/x6u5wH

我有两个问题,但公平地说,我会把它们分成两个帖子。一旦发布,我会在帖子顶部添加第二个问题的链接。

摘要 如果您运行上述小提琴,您将看到结果显示正在处理哪个JProperty。细

问题是“立即祖先财产名称”的值,该名称当前显示预期值。但是,如果我希望祖先的值显示最近父母的祖先的JProperty名称怎么办?我将用“最近的父”解释我的意思,因为可能有一个我不知道的实际JSON术语。

为了说明,让我们关注我的JSON中的Data7属性。请注意,它是JArray Data5中的第二个元素(Data6是第一个)。

问题 我想要做的是创建一个查看当前属性的Linq查询,然后在祖先树中查找最近的父属性。从Data8开始,最近的父级将是Data7。但是,Data7最近的父级是Data4,而不是Data5。我不认为Data5是最近的父,因为Data5是一个包含Data6和Data7的JArray。当涉及JArrays时,我想要JArray的父级,无论是JArray还是JObject。 Data6的父级也是Data4。

Data4的父级将是Data3;对于Data3,父级将是Data2;对于Data2,父级将是Data1(数据将具有空/空父级)。

感谢。

P.S。如果小提琴消失了,这里是有问题的代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;

    public class Program
    {
        public static void Main()
        {
            string json = @"{
  ""Data1"": {
    ""SPECIAL"": ""QQ01"",
    ""AA"": ""QQ"",
    ""BB"": ""QQ"",
    ""Data2"": [
      {
        ""SPECIAL"": ""QQ02"",
        ""AA"": ""QQ"",
        ""BB"": ""QQ"",
        ""CC"": ""QQ"",
        ""Data3"": [
          {
            ""SPECIAL"": ""QQ03"",
            ""AA"": ""QQ"",
            ""CC"": ""QQ"",
            ""Data4"": [
              {
                ""SPECIAL"": ""QQ04"",
                ""AA"": ""QQ"",
                ""CC"": ""QQ"",
                ""Data5"": [
                  {
                    ""SPECIAL"": ""QQ05"",
                    ""AA"": ""QQ"",
                    ""CC"": ""QQ"",
                    ""Data6"": [
                      {
                        ""SPECIAL"": ""QQ06"",
                        ""AA"": ""QQ"",
                        ""CC"": ""QQ""
                      }
                    ]
                  },
                  {
                    ""SPECIAL"": ""QQ07"",
                    ""AA"": ""QQ"",
                    ""CC"": ""QQ"",
                    ""DD"": ""QQ"",
                    ""Data7"": [
                      {
                        ""SPECIAL"": ""QQ08"",
                        ""AA"": ""QQ"",
                        ""CC"": ""QQ"",
                        ""Data8"": [
                          {
                            ""SPECIAL"": ""QQ09"",
                            ""AA"": ""QQ"",
                            ""BB"": ""QQ"",
                            ""CC"": ""QQ""
                          }
                        ]
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  },
  ""Data9"":
  {
    ""SPECIAL"": ""QQ10"",
    ""AA"": ""QQ"",
    ""BB"": ""QQ"",
    ""CC"": ""QQ"",
    ""Data10"":
    {
        ""SPECIAL"": ""QQ11"",
        ""AA"": ""QQ"",
        ""BB"": ""QQ"",
        ""CC"": ""QQ"",
        ""Data11"":
        {
            ""SPECIAL"": ""QQ12"",
            ""AA"": ""QQ"",
            ""BB"": ""QQ"",
            ""CC"": ""QQ""                  
        }
    }
  }
}";

            List<JObject> list = 
                JObject.Parse(json)
                .Descendants()
                .Where(jt => jt.Type == JTokenType.Property && ((JProperty)jt).Value.HasValues)
                .Cast<JProperty>()
                .Select(prop =>
                {

                    var parentName = prop.Ancestors()
                                         .Where(jt => jt.Type == JTokenType.Property)
                                         .Select(jt => ((JProperty)jt).Name)
                                         .FirstOrDefault();
                    var obj = new JObject(new JProperty("Current Property", prop.Name));

                    obj.Add(new JProperty("Immediate Ancestor Property Name", parentName ?? ""));


    // HERE***  (Question 2)
                    // here I would like to be able to add a new JObject property (just like I do above with "Parent")
                    // but this time I want to add the property values for Item1 and Item2 for a specific ancestor. 
                    // To achieve this, I want to grab all of the properties for an ancestor.

                    return obj;
                })
                .ToList();


            for (int i = 0; i < list.Count; i++)
            {
                Console.WriteLine("list[" + i + "]:");
                Console.WriteLine(list[i].ToString(Formatting.None));
                Console.WriteLine();
            }
        }
    }

1 个答案:

答案 0 :(得分:1)

听起来好像你想要最低的父JProperty,其值不是一个数组,或者只是一个项目的数组。如果是这样,你可以这样做:

var list = 
    JObject.Parse(json)
    .Descendants()
    .OfType<JProperty>()
    .Where(prop => prop.Value.HasValues)
    .Select(prop =>
    {

        var parentName = prop.Ancestors()
                             .OfType<JProperty>()
                             .Where(p => !(p.Value is JArray && ((JArray)p.Value).Count > 1))
                             .Select(p => p.Name)
                             .FirstOrDefault();
        var obj = new JObject(new JProperty("Current Property", prop.Name));

        obj.Add(new JProperty("Immediate Ancestor Property Name", parentName ?? ""));


        return obj;
    })
    .ToList();

这将提供所需的父列表。原型fiddle