C# 从分层JSON中挑选简单属性
*尽管其他用户对我的标题进行了编辑,但我正在寻找一种使用C#**中JSON.NET库的解决方案。 包含psuedocode的回复很好!:) 我正在尝试使用JSON数据集提供的分层数据。我正在使用C#和JSON.NET。如果有帮助的话,我愿意在一般情况下使用Linq,特别是在JSON.NET中使用Linq;否则,使用非Linq C#/JSON.NET就可以了 理想情况下,我正努力优雅地完成两件事:C# 从分层JSON中挑选简单属性,c#,json.net,C#,Json.net,*尽管其他用户对我的标题进行了编辑,但我正在寻找一种使用C#**中JSON.NET库的解决方案。 包含psuedocode的回复很好!:) 我正在尝试使用JSON数据集提供的分层数据。我正在使用C#和JSON.NET。如果有帮助的话,我愿意在一般情况下使用Linq,特别是在JSON.NET中使用Linq;否则,使用非Linq C#/JSON.NET就可以了 理想情况下,我正努力优雅地完成两件事: 我想提取表示每个分支及其自身属性的JSON,而不是它的子(嵌套)分支对象(稍后我将进一步解释) 我希
{
"Branch1": {
"Prop1A" : "1A",
"Prop1B" : "1B",
"Prop1C" : "1C",
"Branch2" : {
"Prop2A" : "2A",
"Prop2B" : "2B",
"Prop2C" : "2C",
"Branch3" : {
"Prop3A" : "3A",
"Prop3B" : "3B",
"Prop3C" : "3C"
}
}
}
}
与目标1相关(从上面):
给定由嵌套JSON对象组成的JSON,我只想为每个分支挑选简单(字符串)属性。例如,我想提取Branch1的JSON,它只包含Prop1A、Prop1B和Prop1C属性。然后我想提取Branch2的JSON,该JSON只包含Prop2A、Prop2B和Prop2C属性等。我意识到我可以将整个JSON表示为一个JSON.NET JToken对象,然后遍历其子对象()并只查找JTokenType.Property类型,但是,也许有一种更优雅的方法可以使用Linq快速选择属性类型。。。?最后,我将有三个单独的JSON对象,如下所示:
{
"Prop1A" : "1A",
"Prop1B" : "1B",
"Prop1C" : "1C",
"Parent" : ""
}
JSON对象1:
{
"Prop1A" : "1A",
"Prop1B" : "1B",
"Prop1C" : "1C"
}
JSON对象2:
{
"Prop2A" : "2A",
"Prop2B" : "2B",
"Prop2C" : "2C"
}
JSON对象3:
{
“Prop3A”:“3A”,
“Prop3B”:“3B”,
“Prop3C”:“3C”
}
与目标2相关(从上面):
理想情况下,上面提取的每个JSON也会有一个属性指示其父级。因此,最终的JSON对象如下所示:
{
"Prop1A" : "1A",
"Prop1B" : "1B",
"Prop1C" : "1C",
"Parent" : ""
}
以及:
以及:
有什么想法吗?您可以使用它来查找JSON层次结构中的所有对象,然后对于每个对象,循环遍历它的对象,并过滤掉那些属于原语的对象。因此,以下查询将创建一个列表
,其中包含所需的属性名称和值:
var root = (JContainer)JToken.Parse(jsonString);
var query1 = from o in root.DescendantsAndSelf().OfType<JObject>() // Find objects
let l = o.Properties().Where(p => p.Value is JValue) // Select their primitive properties
where l.Any() // Skip objects with no properties
select new JObject(l); // And return a JObject
var list1 = query1.ToList();
可以使用以下方法增强查询,以包括一个合成的“父”属性,该属性给出包含对象的直接父属性的名称:
生成以下输出,显示JObject
列表包含您需要的内容:
var root = (JContainer)JToken.Parse(jsonString);
var query1 = from o in root.DescendantsAndSelf().OfType<JObject>() // Find objects
let l = o.Properties().Where(p => p.Value is JValue) // Select their primitive properties
where l.Any() // Skip objects with no properties
select new JObject(l); // And return a JObject
var list1 = query1.ToList();
请注意,如果JSON对象本身有一个名为
“Parent”
的属性,那么JObject
构造函数可能会抛出一个重复的键异常。为什么“Branch1”
不是第一个“Prop1A”
对象的父对象?这毕竟是直接的父属性名称,因为本例中的JSON表示JSON对象的父子层次关系。在本例中,对象1位于对象2的父对象中,对象2是对象3的父对象。对象1映射到Branch1(一个JSON对象,没有父对象,只有一个子分支——分支2);对象2映射到Branch2(一个JSON对象,其父对象为Branch1,子对象为Branch3);对象3映射到Branch3(一个JSON对象,其父对象为Branch2,没有子分支)。值得赞赏——但需要不同/独立的JSON对象与算法,不尝试重新构造现有JSON,而是尝试将原始JSON分解为多个更小的JSON对象,通过与父对象的链接保留层次结构。请参阅对原帖子的澄清。抱歉,可能没有让请求更清楚。还有,爱后代和自己()。谢谢你。我不知道你说的通过链接到家长来保留层次结构是什么意思。Linq到JSON中的父/子关系是双向的,因此,如果子对象“链接”到父对象,则父对象必须具有引用子对象的属性,这不是您在问题中显示的属性。另外,你只是想得到一个JObject
对象列表,而不是一个字典列表吗?当然,公平的问题是:最终,这些JSON对象将成为C#对象。Branch1将是一个表示Windows GUI控件容器(例如表单控件)的对象;Branch2将是窗体内的容器对象(例如面板);Branch3将是面板内的一个控件。我只知道控件的父对象就足够了。JObject对象列表就可以了,其中[0]有分支1,[1]有分支2,等等。谢谢。@Jazimov-answer被修改为返回JObjectsSplendid列表!太感谢你了!如果可以,请提供除在线JSON.NET文档之外的任何关于掌握Linq for JSON.NET的参考资料,我发现这很难使用/理解。。。
let l = o.Properties().Where(p => p.Value.Type == JTokenType.String) // Select their string-valued properties
var query2 = from o in root.DescendantsAndSelf().OfType<JObject>() // Find objects
let l = o.Properties().Where(p => p.Value is JValue) // Select their primitive properties
where l.Any() // Skip objects with no properties
// Add synthetic "Parent" property
let l2 = l.Concat(new[] { new JProperty("Parent", o.Ancestors().OfType<JProperty>().Select(a => a.Name).FirstOrDefault() ?? "") })
select new JObject(l2); // And return a JObject.
var list2 = query2.ToList();
var query3 = from o in root.DescendantsAndSelf().OfType<JObject>() // Find objects
let l = o.Properties().Where(p => p.Value is JValue) // Select their primitive properties
where l.Any() // Skip objects with no properties
// Add synthetic "Parent" property
let l2 = l.Concat(new[] { new JProperty("Parent", o.Ancestors().OfType<JProperty>().Skip(1).Select(a => a.Name).FirstOrDefault() ?? "") })
select new JObject(l2); // And return a JObject.
var list3 = query3.ToList();
Console.WriteLine(JsonConvert.SerializeObject(list3, Formatting.Indented));
[
{
"Prop1A": "1A",
"Prop1B": "1B",
"Prop1C": "1C",
"Parent": ""
},
{
"Prop2A": "2A",
"Prop2B": "2B",
"Prop2C": "2C",
"Parent": "Branch1"
},
{
"Prop3A": "3A",
"Prop3B": "3B",
"Prop3C": "3C",
"Parent": "Branch2"
}
]