MrMilkShake
MrMilkShake

Reputation: 51

How to loop through nested JSON objects in C#?

I am working on a C# project where I need to call an API and parse through the JSON response.

The JSON response:

{
    "version": "3.9.1",
     "data": {
        "obj1": {
            "version": "1.0.0",
            "id": "obj1",
            "name": "Object 1",
            "title": "Object 1",
            "info": {
                "info1": 8,
                "info2": 4,
                "info3": 3
            },
            "image": {
                "full": "Object1.png",
                "w": 64,
                "h": 64
            },
            "tags": [
                "Tag1",
                "Tag2"
            ]
        },
        "obj2": {
            "version": "1.0.0",
            "id": "obj2",
            "name": "Object 2",
            "title": "Object 2",
            "info": {
                "info1": 1,
                "info2": 6,
                "info3": 7
            },
            "image": {
                "full": "Object2.png",
                "w": 64,
                "h": 64
            },
            "tags": [
                "Tag1",
                "Tag6"
            ]
        },
        "obj3": {
            "version": "1.0.0",
            "id": "obj3",
            "name": "Object 3",
            "title": "Object 3",
            "info": {
                "info1": 0,
                "info2": 1,
                "info3": 2
            },
            "image": {
                "full": "Object3.png",
                "w": 64,
                "h": 64
            },
            "tags": [
                "Tag7",
                "Tag8"
            ]
        }
    }
}

With this response, I want to loop through all the objects located inside data. The number of objects inside data isn't always the same; it is possible that there will only be one object or ten objects.

The problem I ran into is that I can't loop through the data property because of the following error:

foreach statement cannot operate on variables of type 'Objects' because 'Objects' does not contain a public instance or extension definition for 'GetEnumerator'

I know why I am getting the error, but I can't find a way of fixing my problem.

My code:

MainWindow.xaml.cs

WebRequest request = WebRequest.Create(path);
WebResponse response = request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());

string ReaderJson = reader.ReadToEnd();

var JsonResponse = JsonConvert.DeserializeObject<Response>(ReaderJson);

foreach (var obj in JsonResponse.data)
{
    Console.WriteLine(obj.ToString());
}

JsonParser.cs

    public class Response
    {
        public string version { get; set; }
        public Objects data { get; set; }
    }

    public class Objects
    {
        public string id { get; set; }
        public string name { get; set; }
        public string title { get; set; }
        public Info info { get; set; }
        public Images images { get; set; }
    }

    public class Info
    {
        public int info1 { get; set; }
        public int info2 { get; set; }
        public int info3 { get; set; }
    }

    public class Images
    {
        public string full { get; set; }
        public int w { get; set; }
        public int h { get; set; }
    }

How can I loop through all the objects inside data without calling them using obj1, obj2, etc.?

Upvotes: 0

Views: 2289

Answers (1)

Jeremy Caney
Jeremy Caney

Reputation: 7604

The problem here is that your JSON schema defines a dictionary for data, but your data property returns a single instance of your Objects class.

Data Model

What you want is for your Response class to look something like this:

public class Response
{
    public string version { get; set; }
    public Dictionary<string, Objects> data { get; set; }
}

Everything else should be fine.

Looping Through Data

Given the above, you can now loop through the data dictionary using something like:

foreach (var obj in JsonResponse.data)
{
    Console.WriteLine(obj.Key);
}

Note: When looping through a Dictionary<TKey, TValue>, an enumeration of KeyValuePair<TKey, TValue>s will be returned, with your key (i.e., obj1) in the Key property, and your object in the Value property.

Naming Conventions

Obviously, the name Objects doesn't makes sense here, since it represents a single object, not a collection of objects. I'm keeping it Objects for consistency with your code, but you'll want to give it a singular name. I assume that was just left over from you wanting it to represent a collection.

Upvotes: 1

Related Questions