C# 使用json.net和linq在json中查找模式
我正在搜索一个json文件,其结构如下:C# 使用json.net和linq在json中查找模式,c#,json,linq,json.net,C#,Json,Linq,Json.net,我正在搜索一个json文件,其结构如下: { "objects": [ { "name": "obj1", "state": { "type": 4, "childs": [ "state": { "type": 5,
{
"objects": [
{
"name": "obj1",
"state": {
"type": 4,
"childs": [
"state": {
"type": 5,
...
状态可以作为子级包含状态,直到达到任意级别。现在,我试图找到所有包含特定状态模式的对象,例如,状态4与子状态5与子状态2
到目前为止,我的代码是这样的
JObject o = JObject.Parse(System.IO.File.ReadAllText(@"j.json"));
var oObjects=
from p in o["objects"]
where (string)p["state"] == "4"
select (string)p["name"];
如何扩展代码以查找任何级别上包含搜索模式的所有对象?一个选项是将json转换为xml,然后使用xpath查询获取节点列表
string json = System.IO.File.ReadAllText(@"j.json");
XmlDocument document = (XmlDocument)JsonConvert.DeserializeXmlNode(json);
XmlNodeList nodes = document.SelectNodes("//name[../state[type[.=4] and childs/state[type[.=5] and childs/state[type[.=2]]]]]");
您可以为此使用:
var objects = o.SelectTokens("$.objects[?(@.state.type == 4
&& @.state.childs[*].state.type == 5)].name")
.Select(s => (string)s)
.ToList();
要使其适用于不确定级别,则需要使用如下递归方法:
void Main()
{
var str = @"{
""objects"": [
{
""name"": ""obj1"",
""state"": {
""type"": 4,
""childs"": [
{
""state"": {
""type"": 5
}
}
]
}
}
]
}";
var obj = JObject.Parse(str);
GetValidObjects(obj, new string[] { "4", "5" }); // Name list of valid objects
}
以及定义如下的帮助器方法:
public IEnumerable<string> GetValidObjects(JObject obj, IEnumerable<string> values)
{
return obj["objects"]
.Where(i => (string)i["state"]["type"] == values.First() && ContainsState((JArray)i["state"]["childs"], values.Skip(1)))
.Select(i => (string)i["name"]);
}
public bool ContainsState(JArray childs, IEnumerable<string> values)
{
if (childs == null)
{
return values.Count() == 0;
}
return childs.Any(i => (string)i["state"]["type"] == values.First() && ContainsState((JArray)i["state"]["childs"], values.Skip(1)));
}
public IEnumerable GetValidObjects(JObject对象,IEnumerable值)
{
返回对象[“对象”]
.Where(i=>(string)i[“state”][“type”]==values.First()&&containssState((JArray)i[“state”][“childs”],values.Skip(1)))
。选择(i=>(string)i[“name”]);
}
公共布尔包含状态(JArray childs,IEnumerable值)
{
if(childs==null)
{
返回值。Count()==0;
}
返回childs.Any(i=>(string)i[“state”][“type”]==values.First()&&containssState((JArray)i[“state”][“childs”],values.Skip(1));
}
查看递归。您可以尝试使用。
递归下降运算符。看见了解这个助手方法也很好,但它不适用于除2之外的其他级别。