我正在搜索一个 json 文件,结构如下:
{
"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"];
如何扩展代码以查找任何级别上包含搜索模式的所有对象?
要使其适用于无限级别,则需要使用如下所示的递归方法:
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)));
}
一个选项是将 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]]]]]");
你可以使用SelectTokens来实现这一点:
var objects = o.SelectTokens("$.objects[?(@.state.type == 4
&& @.state.childs[*].state.type == 5)].name")
.Select(s => (string)s)
.ToList();