Deserializing JSON array into strongly typed .NET object
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<o开发者_如何学Pythonbject>
. 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.
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
try
List<TheUser> friends = jsonSerializer.Deserialize<List<TheUser>>(response);
This worked for me for deserializing JSON into an array of objects:
List<TheUser> friends = JsonConvert.DeserializeObject<List<TheUser>>(response);
This solution seems to work for me and gets around having to code a bunch of classes with "Data" in them.
public interface IDataResponse<T> where T : class
{
List<T> Data { get; set; }
}
public class DataResponse<T> : IDataResponse<T> where T : class
{
[JsonProperty("data")]
public List<T> Data { get; set; }
}
I should have included this to begin with, here is an example method using the above:
public List<TheUser> GetUser()
{
var results = GetUserJson();
var userList = JsonConvert.DeserializeObject<DataResponse<TheUser>>(results.ToString());
return userList.Data.ToList();
}
Json.NET - Documentation
http://james.newtonking.com/json/help/index.html?topic=html/SelectToken.htm
Interpretation for the author
var o = JObject.Parse(response);
var a = o.SelectToken("data").Select(jt => jt.ToObject<TheUser>()).ToList();
Pat, the json structure looks very familiar to a problem i described here - The answer for me was to treat the json representation as a Dictionary<TKey, TValue>, even though there was only 1 entry.
If I am correct your key is of type string and the value of a List<T> where T represents the class 'TheUser'
HTH
PS - if you want better serialisation perf check out using Silverlight Serializer, you'll need to build a WP7 version, Shameless plug - I wrote a blog post about this
I like this approach, it is visual for me.
using (var webClient = new WebClient())
{
var response = webClient.DownloadString(url);
JObject result = JObject.Parse(response);
var users = result.SelectToken("data");
List<User> userList = JsonConvert.DeserializeObject<List<User>>(users.ToString());
}
I suspect the problem is because the json represents an object with the list of users as a property. Try deserializing to something like:
public class UsersResponse
{
public List<User> Data { get; set; }
}
精彩评论