1
votes

I am using Zomato API and I am receiving the following JSON response :

{
"categories": [
    {
      "categories": {
        "id": 1,
        "name": "Delivery"
      }
    },
    {
      "categories": {
        "id": 2,
        "name": "Dine-out"
      }
    },
    {
      "categories": {
        "id": 3,
        "name": "Nightlife"
      }
    },
    {
      "categories": {
        "id": 4,
        "name": "Catching-up"
      }
    },
    {
      "categories": {
        "id": 5,
        "name": "Takeaway"
      }
    },
    {
      "categories": {
        "id": 6,
        "name": "Cafes"
      }
    },
    {
      "categories": {
        "id": 7,
        "name": "Daily Menus"
      }
    },
    {
      "categories": {
        "id": 8,
        "name": "Breakfast"
      }
    },
    {
      "categories": {
        "id": 9,
        "name": "Lunch"
      }
    },
    {
      "categories": {
        "id": 10,
        "name": "Dinner"
      }
    },
    {
      "categories": {
        "id": 11,
        "name": "Pubs & Bars"
      }
    },
    {
      "categories": {
        "id": 13,
        "name": "Pocket Friendly Delivery"
      }
    },
    {
      "categories": {
        "id": 14,
        "name": "Clubs & Lounges"
      }
    }
  ]
}

I want to deserialize this response and I created the following classes :

public class CategoriesTop
{
    public List<CategoriesBottom> categories { get; set; }
}
public class CategoriesBottom
{
    public Categorie categorie { get; set; }
}
public class Categorie
{
    public int id { get; set; }
    public string name { get; set; }
}

And I am using this code to get the response :

public Form1()
    {
        InitializeComponent();

        HttpWebRequest webRequest =
                WebRequest.Create("https://developers.zomato.com/api/v2.1/categories")
                        as HttpWebRequest;
        HttpWebResponse webResponse = null;
        webRequest.Headers.Add("X-Zomato-API-Key", "509ce9e4863960cdc076fb3817cc238e");
        //you can get KeyValue by registering with Zomato.
        webRequest.Method = "GET";
        webResponse = (HttpWebResponse)webRequest.GetResponse();
        if (webResponse.StatusCode == HttpStatusCode.OK)
        {
            StreamReader responseReader = new
                               StreamReader(webResponse.GetResponseStream());
            string responseData = responseReader.ReadToEnd();
            //XmlDocument doc = new XmlDocument();
            //doc.LoadXml(responseData);
            //XmlNodeReader xmlReader = new XmlNodeReader(doc);
            //DataSet ds = new DataSet();
            //ds.ReadXml(xmlReader);
            List<CategoriesBottom> l = JsonConvert.DeserializeObject<List<CategoriesBottom>>(responseData);
            foreach(CategoriesBottom c in l)
            {
                cmbCatName.Items.Add(c.categorie.name);
            }
        }
    }

When I run the program I receive an error on the JSON.Convert line :

Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[WindowsFormsApp1.CategoriesBottom]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.

So I think I have a problem with the deserialize code or the classes are defined incorrectly. Any help will be appreciated.

3
Hi, the error is specifying that there is a mismatch between your JSON structure and the type which you would deserialise the data into. In this case, your classes do not match the JSON code. Try deserialising the data as a Categorie[] - Spook Kruger
@SpookKruger could you please give me an indication on how to do that? - RoyNasr

3 Answers

2
votes

Try to change the property to to match the json data:

public class CategoriesBottom
{
    public Categorie categories { get; set; }
}

Also serialize your CategoriesTop type:

CategoriesTop ct = JsonConvert.DeserializeObject<CategoriesTop>(responseData);
1
votes

The easiest way to generate C# classes for JSON structures is via json2csharp on-line service.

The first problem is that your property in CategoriesBottom is called categorie while the structure contains categories

public class CategoriesBottom
{
    [JsonProperty( "categories" )]
    public Categorie categorie { get; set; }
}

Also you deserialize a List<CategoriesBottom> which is not working, because the whole list is wrapped in another object (CategoriesTop). So you rather should do the following:

JsonConvert.DeserializeObject<CategoriesTop>(responseData);
1
votes

Use RestSharp for getting the data from other source. RestSharp has a great feature to deserialize response to class.

This is the example from the RestSharp wiki:

 IRestResponse<Person> response2 = client.Execute<Person>(request);
 var name = response2.Data.Name;

With that you already got the result. Please check the documentation for further information. You can directly install this package using nuget and start to use it.