这篇文章旨在提出一个与我最近的其他文章(从Hierarchical JSON Part II中挑选简单属性)有关的更直接的问题:
给定嵌套的JSON文档,如下所示:
{
"Array1": {
"Array1A": [
{ "Item1": "1" },
{ "Item2": "2" },
{ "Item3": "3" }
],
"Array1B": [
{ "Item1": "1" },
{ "Item2": "2" },
{ "Item3": "3" }
]
},
"Array2": {
"Array2A": [
{ "Item1": "1" },
{ "Item2": "2" },
{ "Item3": "3" }
]
},
"Array3": {
"Array3A": [
{ "Item1": "1" },
{ "Item2": "2" },
{ "Item3": "3" }
],
"Array3B": [
{ "Item1": "1" },
{ "Item2": "2" },
{
"Array3B1": [
{ "Item1": "1" },
{ "Item2": "2" },
{ "Item3": "3" }
]
}
],
"Array3C": [
{ "Item1": "1" },
{ "Item2": "2" },
{ "Item3": "3" }
]
}
}
Run Code Online (Sandbox Code Playgroud)
(注意:以上已通过JSLint验证。)
注意JSON是动态的-我事先不知道会有多少个数组或数组嵌套的深度。
Goal:
My goal is to represent each array (that is, Array1, Array2, Array3, Array3A, Array3B, and Array3B1) in a List<JObject> object. Each item in the list will be a collection of JProperty objects containing that array's string properties. Because the List doesn't itself model hierarchical data, I would need to add a synthetic property to each List<JObject> item that references the parent of that array. Thus, the parent of Array1 is an empty string; Array2 is Array1, Array3 is Array2, Array3A is Array3, Array3B is Array3, and Array 3B1 is Array3B...
Question:
1. How can I use C# Linq to create a List<JObject> object that looks like this:
list[0]:
{"Name":"Array1","Parent":""}
list[1]:
{"Name":"Array1A","Item1":"1","Item2":"2","Item3":"3","Parent":"Array1"}
list[2]:
{"Name":"Array1B","Item1":"1","Item2":"2","Item3":"3","Parent":"Array1"}
list[3]:
{"Name":"Array2","Parent":""}
list[4]:
{"Name":"Array2A","Item1":"1","Item2":"2","Item3":"3","Parent":"Array2"}
list[5]:
{"Name":"Array3","Parent":""}
list[6]:
{"Name":"Array3A","Item1":"1","Item2":"2","Item3":"3","Parent":"Array3"}
list[7]:
{"Name":"Array3B","Item1":"1","Item2":"2","Parent":"Array3"}
list[8]:
{"Name":"Array3B1","Item1":"1","Item2":"2","Item3":"3","Parent":"ArrayB"}
list[9]:
{"Name":"Array3C","Item1":"1","Item2":"2","Item3":"3","Parent":"Array3"}
Run Code Online (Sandbox Code Playgroud)
Please note that:
List<JObject> contains only string properties. 这样的事情怎么样:
List<JObject> list =
JObject.Parse(json)
.Descendants()
.Where(jt => jt.Type == JTokenType.Property && ((JProperty)jt).Value.HasValues)
.Cast<JProperty>()
.Select(prop =>
{
var obj = new JObject(new JProperty("Name", prop.Name));
if (prop.Value.Type == JTokenType.Array)
{
var items = prop.Value.Children<JObject>()
.SelectMany(jo => jo.Properties())
.Where(jp => jp.Value.Type == JTokenType.String);
obj.Add(items);
}
var parentName = prop.Ancestors()
.Where(jt => jt.Type == JTokenType.Property)
.Select(jt => ((JProperty)jt).Name)
.FirstOrDefault();
obj.Add("Parent", parentName ?? "");
return obj;
})
.ToList();
Run Code Online (Sandbox Code Playgroud)
小提琴:https : //dotnetfiddle.net/FMxzls
如果您对LINQ-to-JSON不太熟悉,请按以下步骤进行分解:
将json字符串解析为JObject
JObject.Parse(json)
Run Code Online (Sandbox Code Playgroud)从该JObject中获取其所有后代JToken
.Descendants()
Run Code Online (Sandbox Code Playgroud)将该列表过滤为仅JProperty,其值具有子级
.Where(jt => jt.Type == JTokenType.Property && ((JProperty)jt).Value.HasValues)
Run Code Online (Sandbox Code Playgroud)将JTokens转换为JProperty,以使其在下一步中更易于使用
.Cast<JProperty>()
Run Code Online (Sandbox Code Playgroud)现在,对于我们选择的每个JProperty,将其转换如下:
.Select(prop =>
{
Run Code Online (Sandbox Code Playgroud)创建一个新的JObject并将JProperty的名称添加为Name新对象的属性
var obj = new JObject(new JProperty("Name", prop.Name));
Run Code Online (Sandbox Code Playgroud)如果JProperty的值是一个数组...
if (prop.Value.Type == JTokenType.Array)
{
Run Code Online (Sandbox Code Playgroud)获取数组的所有直接子对象均为JObjects
var items = prop.Value.Children<JObject>()
Run Code Online (Sandbox Code Playgroud)从这些JObjects中,获取所有JProperties
.SelectMany(jo => jo.Properties())
Run Code Online (Sandbox Code Playgroud)筛选那些JProperty,使其仅包含其值为字符串的JProperty)
.Where(jp => jp.Value.Type == JTokenType.String);
Run Code Online (Sandbox Code Playgroud)将这些项目JProperties添加到我们之前创建的新JObject中
obj.Add(items);
}
Run Code Online (Sandbox Code Playgroud)接下来,找到当前JProperty的第一个祖先JProperty并获取其名称
var parentName = prop.Ancestors()
.Where(jt => jt.Type == JTokenType.Property)
.Select(jt => ((JProperty)jt).Name)
.FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)将父名称添加到我们正在构建的JObject中;如果没有父母,请使用空字符串
obj.Add("Parent", parentName ?? "");
Run Code Online (Sandbox Code Playgroud)继续下一个转换
return obj;
})
Run Code Online (Sandbox Code Playgroud)最后,将我们构建的所有JObjects放入列表中。
.ToList();
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
2686 次 |
| 最近记录: |