2

I'm not sure how to define the data property to deserialize the following json data...

{
"response": {
    "total_rows": 39,
    "data": [
      [
        "XXXXXXXXXXXXXXXXXBs2VI",
        "a7ac4aa7-7211-4116-be57-0c36fc2abeee",
        "AAAAAA",
        "Crn Burnley & Victoria St",
        "Richmond",
        "VIC",
        "3121",
        "555-555-555",
        null,
        "Real Estate & Home Improvement > Storage",
        null,
        null,
        -37.8114511488511,
        145.009782837163
      ],
      [ .. ]
      [ .. ]
      ....
    },
    status = "ok"
}

so I had ..

public class ResultData
{
    public Response Response { get; set; }
    public string Status { get; set; }
}

and....

public class Response
{
    public int total_rows { get; set; }
    public IList<string> data { get; set; }
}

but that was throwing an exception, saying "Can't cast float to string". SO it was trying to add those last two floats, into the List<> .. but failed.

How can I fix this, please? (I can't control the json output).

Cheers :)

Update

It looks like the content of the data json property is a fixed size array with fixed object types. So is there a way i could define that, in my .NET code so JSON.NET knows how to exactly deserialize it? Do I need to make a custom json deserializer for that json property?

Community
  • 1
  • 1
Pure.Krome
  • 84,693
  • 113
  • 396
  • 647
  • 1
    *Rollback* Sif remove my salutation! Shees -- haven't we all been down this path many many many many times, SO folks? – Pure.Krome Feb 21 '11 at 12:22

4 Answers4

3

If you're using .NET 4.0 then you might like to consider using dynamic when dealing with JSON.

I posted some code that shows one way of setting that up on another question.

In your example you would be able to do:

var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new[] { new DynamicJsonConverter() });

dynamic obj = serializer.Deserialize(json, typeof(object));

if (obj.status != "ok")
    throw new OopsException();

int rowCount = obj.total_rows;

foreach (var row in obj.data) {
    string code1 = row[0];
    string code2 = row[1];
    string code3 = row[2];
    string address = row[3];
    string suburb = row[4];
    string state = row[5];
    string postcode = row[6];
    string phone = row[7];
    string something1 = row[8];
    string name = row[9];
    string something2 = row[10];
    string something3 = row[11];
    decimal longitude = row[12];
    decimal latitude = row[13];

    // TODO use above values
}
Community
  • 1
  • 1
Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
  • That's pretty interesting, IMO :) so this is using the built in JavascriptSerializer in the .NET library, right? I'm using the 3rd party library RestSharp to handle the heavy lifting of calling the RESTful service which returns JSON .. and in that heavy lifting ... it uses JSON.NET to deserialize. I wonder if it's possible to define the deserializtion service .. to be you code? – Pure.Krome Feb 22 '11 at 04:28
  • @Pure.Krome, I'm not familiar with RestSharp or JSON.NET. In the past I've just used simple WebRequests to get at response strings that can be passed to the deserialisers shown above. That's simple enough, once you have helpers like this. And yes, it's using the built-in JavaScriptSerializer. Note that if you're iterating over these dynamic structures heavily then you might find better performance if you copy all the data out once to a strongly-typed structure and hit it from there. – Drew Noakes Feb 22 '11 at 13:02
1

You have string and numbers in your array. You have to use object instead of string has the list type.

public class Response
{
    public int total_rows { get; set; }
    public IList<object> data { get; set; }
}
Nekresh
  • 2,948
  • 23
  • 28
1

I am not sure if this is the best way to do it, but I got it working by doing this:

public class Response
{
    [JsonProperty(PropertyName = "total_rows")]
    public int TotalRows { get; set; }
    public IList<MyPoco> Data { get; set; }
}

Now, the data property will NOT get auto-populated by the JSON library, which is 100% fine.

I then do this:

RestResponse<ResultData> response = client.Execute<ResultData>(restRequest);

ResultData data = response.Data;

if (data != null)
{
    // Now the Data property will be null, so we need to parse that badboy.
    JObject linqData = JObject.Parse(response.Content);
    var array = linqData["response"]["data"] as JArray;
    if (array != null)
    {
        data.Response.Data = 
            (from x in array
            select new MyPoco
                        {
                            SubjectKey = x[0].Value<string>(),
                            UUid = x[1].Value<string>(),
                            Name = x[2].Value<string>(),
                            Address = x[3].Value<string>(),
                            City = x[4].Value<string>(),
                            Territory = x[5].Value<string>(),
                            Postcode = x[6].Value<string>(),
                            Telephone = x[7].Value<string>(),
                            Category = x[9].Value<string>(),
                            Website = x[10].Value<string>(),
                            Email = x[11].Value<string>(),
                            Latitude = x[12].Value<float>(),
                            Longitude = x[13].Value<float>()
                        }).ToList();
    }
}

So, I don't let the JSON library to the auto-extraction for that one List of List-Objects, but I use some Linq-To-Json and extract those bad boys.

Not completely happy, but it works.

halfer
  • 19,824
  • 17
  • 99
  • 186
Pure.Krome
  • 84,693
  • 113
  • 396
  • 647
0

It looks like you have a list of lists. In that case, it should be:

public class Response
{
    public int total_rows { get; set; }
    public IList<IList<object>> data { get; set; }
}
Jakob
  • 24,154
  • 8
  • 46
  • 57