Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

json

c#

json.net

I've got a JSON stream coming back from a server, and I need to search for a specific value of the node "ID" using JSON.net to parse the data. And I can almost make it work, but not quite because the results coming back are deeply nested in each other -- this is due to the fact that I'm getting a folder structure back. I've boiled the JSON down to a much simpler version. I'm getting this:

{
    "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
}

I can almost get there by going:

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

I can see in the debug view that it'll parse the object, but won't let me search within.

My ultimate goal is to be able to search for "route3" and get back 19007, since that's the ID for that route. I've found some results, but all of them assume you know how far nested the object is. The object I'm searching for could be 2 deep or 20 deep.

like image 938
EtanSivad Avatar asked Nov 17 '16 23:11

EtanSivad


2 Answers

My ultimate goal is to be able to search for "route3" and get back 19007

You can use linq and Descendants method of JObject to do it:

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;
like image 124
L.B Avatar answered Nov 01 '22 03:11

L.B


You can use the SelectToken or SelectTokens functions to provide a JPath to search for your desired node. Here is an example that would provide you the route based on name:

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

You can find more documentation on JPath here

like image 41
Jess Anderson Avatar answered Nov 01 '22 02:11

Jess Anderson