繁体   English   中英

在C#中搜索JSON.net对象内的嵌套值

[英]Search for a nested value inside of a JSON.net object in C#

我有一个从服务器返回的JSON流,我需要使用JSON.net搜索节点“ID”的特定值来解析数据。 我几乎可以使它工作,但不完全是因为返回的结果彼此深深地嵌套 - 这是因为我正在获得一个文件夹结构。 我把JSON简化为更简单的版本。 我明白了:

{
    "data": {
        "id": 0,
        "name": "",
        "childFolders": [{
            "id": 19002,
            "name": "Locker",
            "childFolders": [{
                "id": 19003,
                "name": "Folder1",
                "childFolders": [],
                "childComponents": [{
                    "id": 19005,
                    "name": "route1",
                    "state": "STOPPED",
                    "type": "ROUTE"
                }]
            }, {
                "id": 19004,
                "name": "Folder2",
                "childFolders": [],
                "childComponents": [{
                    "id": 19008,
                    "name": "comm1",
                    "state": "STOPPED",
                    "type": "COMMUNICATION_POINT"
                }, {
                    "id": 19006,
                    "name": "route2",
                    "state": "STOPPED",
                    "type": "ROUTE"
                }, {
                    "id": 19007,
                    "name": "route3",
                    "state": "STOPPED",
                    "type": "ROUTE"
                }]
            }],
            "childComponents": []
        }],
        "childComponents": []
    },
    "error": null
}

我几乎可以去那里:

var objects = JObject.Parse(results);
var subobjects = objects["data"]["childFolders"][0]["childFolders"][1];

我可以在调试视图中看到它将解析对象,但不会让我在其中搜索。

我的最终目标是能够搜索“route3”并返回19007,因为那是该路线的ID。 我发现了一些结果,但是所有结果都假设你知道对象的嵌套距离。 我正在寻找的物体可以是2深或20深。

我的最终目标是能够搜索“route3”并返回19007

您可以使用JObject的linqDescendants方法来执行此操作:

var dirs = JObject.Parse(json)
            .Descendants()
            .Where(x=>x is JObject)
            .Where(x=>x["id"]!=null && x["name"]!=null)
            .Select(x =>new { ID= (int)x["id"], Name = (string)x["name"] })
            .ToList();

var id = dirs.Find(x => x.Name == "route3").ID;

您可以使用SelectTokenSelectTokens函数提供JPath来搜索所需的节点。 这是一个基于名称为您提供路线的示例:

JObject.Parse(jsonData)["data"].SelectToken("$..childComponents[?(@.name=='route3')]")

您可以在此处找到有关JPath的更多文档

只需编写一个递归函数:

private Thing FindThing(Thing thing, string name)
{
    if (thing.name == name)
        return thing;
    foreach (var subThing in thing.childFolders.Concat(thing.childComponents))
    {
        var foundSub = FindThing(subThing, name);
        if (foundSub != null)
            return foundSub;
    }
    return null;
}

class RootObject
{
    public Thing data { get; set; }
}

class Thing
{
    public int id { get; set; }
    public string name { get; set; }
    public List<Thing> childFolders { get; set; } = new List<Thing>();
    public List<Thing> childComponents { get; set; } = new List<Thing>();
}

并使用它:

var obj = JsonConvert.DeserializeObject<RootObject>(jsonString);
var result = FindThing(obj.data, "route3");

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM