Linq-To-JSON 向上遍历祖先树以获取最近父级的 JProperty
Linq-To-JSON Walking Up Ancestor Tree To Obtain JProperty for Nearest Parent
我这里有一个fiddle:
https://dotnetfiddle.net/x6u5wH
我有两个问题,但为了公平起见,我将它们分成两个 post。一旦 posted,我将在 post 顶部的第二个问题中添加一个 link。
总结
如果你运行上面的fiddle,你会看到结果显示正在处理哪个J属性。很好
问题是 "Immediate Ancestor Property Name" 的值,当前显示的是预期值。但是,如果我希望祖先的值显示作为最近父代的祖先的 J属性 名称怎么办?我将解释 "nearest parent" 的意思,因为可能有一个我不知道的实际 JSON 术语。
为了说明,让我们关注我的 JSON 中的 Data7 属性。请注意,它是 JArray Data5 中的第二个元素(Data6 是第一个)。
问题
我想做的是创建一个查看当前 属性 的 Linq 查询,然后沿着最近的父 属性 的祖先树向上移动。从 Data8 开始,最近的父级将是 Data7。但是,离 Data7 最近的父级是 Data4,而不是 Data5。我不认为 Data5 是最近的父级,因为 Data5 是一个包含 Data6 和 Data7 的 JArray。当涉及 JArray 时,我想要 JArray 的父级,无论是 JArray 还是 JObject。 Data6 的父级也将是 Data4。
Data4 的父级为 Data3; Data3 的父对象是 Data2;对于 Data2,父级将是 Data1(Data 将具有 null/empty 父级)。
谢谢。
P.S。如果 fiddle 消失了,这里是有问题的代码:
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();
}
}
}
听起来好像您想要最低的父项 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.
我这里有一个fiddle: https://dotnetfiddle.net/x6u5wH
我有两个问题,但为了公平起见,我将它们分成两个 post。一旦 posted,我将在 post 顶部的第二个问题中添加一个 link。
总结 如果你运行上面的fiddle,你会看到结果显示正在处理哪个J属性。很好
问题是 "Immediate Ancestor Property Name" 的值,当前显示的是预期值。但是,如果我希望祖先的值显示作为最近父代的祖先的 J属性 名称怎么办?我将解释 "nearest parent" 的意思,因为可能有一个我不知道的实际 JSON 术语。
为了说明,让我们关注我的 JSON 中的 Data7 属性。请注意,它是 JArray Data5 中的第二个元素(Data6 是第一个)。
问题 我想做的是创建一个查看当前 属性 的 Linq 查询,然后沿着最近的父 属性 的祖先树向上移动。从 Data8 开始,最近的父级将是 Data7。但是,离 Data7 最近的父级是 Data4,而不是 Data5。我不认为 Data5 是最近的父级,因为 Data5 是一个包含 Data6 和 Data7 的 JArray。当涉及 JArray 时,我想要 JArray 的父级,无论是 JArray 还是 JObject。 Data6 的父级也将是 Data4。
Data4 的父级为 Data3; Data3 的父对象是 Data2;对于 Data2,父级将是 Data1(Data 将具有 null/empty 父级)。
谢谢。
P.S。如果 fiddle 消失了,这里是有问题的代码:
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();
}
}
}
听起来好像您想要最低的父项 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.