Torrents
Torrents

Reputation: 585

LINQ method to find the value for a specific key without looping? (Parsing a json in C#)

I'm using the json.net (Newtonsoft) library to parse an API json response. I only need the id values and the rank values. The json looks like this:

{"items":
    [
        {"fields":
            {"entry":
                [
                    {"key":"Customer","value":"ABC Electronics"},
                    {"key":"Status","value":"Untouched"},
                    {"key":"Amount","value":"$1000"},
                    {"key":"rank","value":"3.0"}
                ]
            },
            "id":"1001",
            "owner":"[email protected]"
        },
        {"fields":
            {"entry":
                [
                    {"key":"Customer","value":"General Products"},
                    {"key":"Status","value":"Developing"},
                    {"key":"Amount","value":"$6000"},
                    {"key":"rank","value":"6.0"}
                ]
            },
            "id":"1002",
            "owner":"[email protected]"
        }
    ]
}

I have a method inside my class that makes the request, loops through the json and grabs the id and rank, then adds those values as a new RankScore object to a List class member. My question is if there is a better way to find the "value" where the key == "rank" in the entry array than just looping through it and checking each key. Any LINQ way that I've been unable to find?

public void MakeRequest(apiURL) {
    var requestUrl = new Uri(apiUrl, "/ranks/0");
    HttpWebRequest request = WebRequest.Create(requestUrl) as HttpWebRequest;
    request.Credentials = new NetworkCredential(this.Username, this.Password);

    using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
    {
        using (var reader = new StreamReader(response.GetResponseStream()))
        {
            var token = JObject.Parse(reader.ReadToEnd());
            var items = token["items"];
            foreach (var item in items)
            {
                var id = item.Value<string>("id");
                var entries = item["fields"]["entry"];
                string rank = null;

                // **** Is there a better way to do this? ****
                foreach (var entry in entries) 
                {
                    if (entry.Value<string>("key") == "rank")
                    {
                        rank = entry.Value<string>("value");
                        break;
                    }
                }
                var ranking = new RankScore(int.Parse(id), rank);
                this.Ranks.Add(ranking);
            }

        }
    }
}

Upvotes: 1

Views: 1054

Answers (2)

evanmcdonnal
evanmcdonnal

Reputation: 48096

Simple answer, no. You could let something else do some of the looping for you but it's not like you're going to come up with a solution that performs better by using LINQ (it's also just looping over the collection).

If your goal is simply to clean up your code you could serialize into an object, then you'll have a simpler loop in your code (of course json.NET will be doing plenty of looping);

for (int i = 0; i < Obj.items.Length; i++)
{
    Obj.items[i].id //do something with this here
}

Although I personally wouldn't recommend that. I like the simple method. Another (stupid) idea would be to use RegEx. You would have fewer lines but much worse performance. Basically, you're not going to remove iteration, you can use an abstraction to do some of it but there's really no point. I would just stick with what you have unless you're going to do a lot more with the json. If you intend to do more with the json elsewhere then I would serialize into an object.

Upvotes: 2

Servy
Servy

Reputation: 203830

If you were planning to look up multiple values per JSON result then it would potentially be worthwhile to take the data and put it into a data structure that would allow more efficient searching of what you're looking for. As an example, you could create a Dictionary that mapped the keys to the values, but if you're only going to search the data structure once then creating that Dictionary would be more work than what you're doing, so you should just leave your code the way it is.

You could potentially reduce the amount of code it takes to do what you want (a few simplifications stand out at first glance) but the underlying algorithm of searching through everything wouldn't be changed.

Upvotes: 1

Related Questions