Deserializing JSON array into strongly typed .NET object

Pat Long - Munkii Yebee picture Pat Long - Munkii Yebee · May 12, 2011 · Viewed 111.8k times · Source

When I can call the 3rd party api and get back a single class worth of data everything deserialises fine using this code

TheUser me = jsonSerializer.Deserialize(response, typeof(TheUser)) as TheUser

The problem comes when I try and deserialise JSON response content that is an array, such as

{
   "data": [
      {
         "name": "A Jones",
         "id": "500015763"
      },
      {
         "name": "B Smith",
         "id": "504986213"
      },
      {
         "name": "C Brown",
         "id": "509034361"
      }
   ]
}

I can only get the serialization to work if I use a custom wrapping class around the "data" member and that member needs to be of type List<object>. If it have them as type List<TheUser> I get ArgumentException from the JsonParser DesializeType method.

I originally tried to serialise without a wrapping type like this

List<TheUser> freinds = jsonSerializer.Deserialize(response, typeof(List<TheUser>)) as List<TheUser>;

but that just returns me an empty collection. Surely I must be able to have the array deserialize to a strongly typed list.

Answer

Matt Lacey picture Matt Lacey · May 13, 2011

Afer looking at the source, for WP7 Hammock doesn't actually use Json.Net for JSON parsing. Instead it uses it's own parser which doesn't cope with custom types very well.

If using Json.Net directly it is possible to deserialize to a strongly typed collection inside a wrapper object.

var response = @"
    {
        ""data"": [
            {
                ""name"": ""A Jones"",
                ""id"": ""500015763""
            },
            {
                ""name"": ""B Smith"",
                ""id"": ""504986213""
            },
            {
                ""name"": ""C Brown"",
                ""id"": ""509034361""
            }
        ]
    }
";

var des = (MyClass)Newtonsoft.Json.JsonConvert.DeserializeObject(response, typeof(MyClass));

return des.data.Count.ToString();

and with:

public class MyClass
{
    public List<User> data { get; set; }
}

public class User
{
    public string name { get; set; }
    public string id { get; set; }
}

Having to create the extra object with the data property is annoying but that's a consequence of the way the JSON formatted object is constructed.

Documentation: Serializing and Deserializing JSON