我有一个小提琴: 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();
}
}
}
答案 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。