17
votes

I am trying to read my JSON result.

Here is my RootObject

public class RootObject
{
public int id { get; set; }
public bool is_default { get; set; }
public string name { get; set; }
public int quantity { get; set; }
public string stock { get; set; }
public string unit_cost { get; set; }
}

Here is my JSON result

[{"id": 3636, "is_default": true, "name": "Unit", "quantity": 1, "stock": "100000.00", "unit_cost": "0"}, {"id": 4592, "is_default": false, "name": "Bundle", "quantity": 5, "stock": "100000.00", "unit_cost": "0"}]

Here is my code to read the result

     public static RootObject GetItems(string user, string key, Int32 tid, Int32 pid)
    {
        // Customize URL according to geo location parameters
        var url = string.Format(uniqueItemUrl, user, key, tid, pid);

        // Syncronious Consumption
        var syncClient = new WebClient();

        var content = syncClient.DownloadString(url);

        return JsonConvert.DeserializeObject<RootObject>(content);

    }

But I am having a problem with this error :

Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'avaris_cash_salepoint.BL.UniqueItemDataRootObject' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly. To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array. Path '', line 1, position 1.

at this line: return JsonConvert.DeserializeObject(content);

Any help to fix this error ?

6
What is the content of var content before it gets passed in to DeserializeObject? - Dayan
content contains the json' result , @Dayan - Djama
Does it look exactly as your JSON example above? - Dayan

6 Answers

33
votes

I think the problem you're having is that your JSON is a list of objects when it comes in and it doesnt directly relate to your root class.

var content would look something like this (i assume):

[
  {
    "id": 3636,
    "is_default": true,
    "name": "Unit",
    "quantity": 1,
    "stock": "100000.00",
    "unit_cost": "0"
  },
  {
    "id": 4592,
    "is_default": false,
    "name": "Bundle",
    "quantity": 5,
    "stock": "100000.00",
    "unit_cost": "0"
  }
]

Note: make use of http://jsonviewer.stack.hu/ to format your JSON.

So if you try the following it should work:

  public static List<RootObject> GetItems(string user, string key, Int32 tid, Int32 pid)
    {
        // Customize URL according to geo location parameters
        var url = string.Format(uniqueItemUrl, user, key, tid, pid);

        // Syncronious Consumption
        var syncClient = new WebClient();

        var content = syncClient.DownloadString(url);

        return JsonConvert.DeserializeObject<List<RootObject>>(content);

    }

You will need to then iterate if you don't wish to return a list of RootObject.


I went ahead and tested this in a Console app, worked fine.

enter image description here

4
votes

That's because the json you're getting is an array of your RootObject class, rather than a single instance, change your DeserialiseObject<RootObject> to be something like DeserialiseObject<RootObject[]> (un-tested).

You'll then have to either change your method to return a collection of RootObject or do some further processing on the deserialised object to return a single instance.

If you look at a formatted version of the response you provided:

[
   {
      "id":3636,
      "is_default":true,
      "name":"Unit",
      "quantity":1,
      "stock":"100000.00",
      "unit_cost":"0"
   },
   {
      "id":4592,
      "is_default":false,
      "name":"Bundle",
      "quantity":5,
      "stock":"100000.00",
      "unit_cost":"0"
   }
]

You can see two instances in there.

4
votes

You can use this to solve your problem:

private async void btn_Go_Click(object sender, RoutedEventArgs e)
{
    HttpClient webClient = new HttpClient();
    Uri uri = new Uri("http://www.school-link.net/webservice/get_student/?id=" + txtVCode.Text);
    HttpResponseMessage response = await webClient.GetAsync(uri);
    var jsonString = await response.Content.ReadAsStringAsync();
    var _Data = JsonConvert.DeserializeObject <List<Student>>(jsonString);
    foreach (Student Student in _Data)
    {
        tb1.Text = Student.student_name;
    }
}
1
votes

You have an array, convert it to an object, something like:

data: [{"id": 3636, "is_default": true, "name": "Unit", "quantity": 1, "stock": "100000.00", "unit_cost": "0"}, {"id": 4592, "is_default": false, "name": "Bundle", "quantity": 5, "stock": "100000.00", "unit_cost": "0"}]

0
votes

This could be You

Before trying to consume your json object with another object just check that the api is returning raw json via the browser api/rootobject, for my case i found out that the underlying data provider mssqlserver was not running and throw an unhanded exception !

as simple as that :)

0
votes

To read more than one json tip (array, attribute) I did the following.


var jVariable = JsonConvert.DeserializeObject<YourCommentaryClass>(jsonVariableContent);

change to

var jVariable = JsonConvert.DeserializeObject <List<YourCommentaryClass>>(jsonVariableContent);

Because you cannot see all the bits in the method used in the foreach loop. Example foreach loop

foreach (jsonDonanimSimple Variable in jVariable)
                {    
                    debugOutput(jVariable.Id.ToString());
                    debugOutput(jVariable.Header.ToString());
                    debugOutput(jVariable.Content.ToString());
                }

I also received an error in this loop and changed it as follows.

foreach (jsonDonanimSimple Variable in jVariable)
                    {    
                        debugOutput(Variable.Id.ToString());
                        debugOutput(Variable.Header.ToString());
                        debugOutput(Variable.Content.ToString());
                    }