Десериализация массива JSON в строго типизированный объект .NET - PullRequest
42 голосов
/ 12 мая 2011

Когда я могу вызвать сторонний API и получить данные одного класса, все десериализуется нормально, используя этот код

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

Проблема возникает, когда я пытаюсь десериализовать содержимое ответа JSON, представляющее собой массив, например

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

Я могу заставить сериализацию работать, только если я использую пользовательский класс обтекания вокруг элемента «data», и этот член должен иметь тип List<object>. Если они имеют тип List<TheUser>, я получаю ArgumentException из метода JsonParser DesializeType.

Первоначально я пытался сериализовать без типа обтекания, как это

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

но это просто возвращает мне пустую коллекцию. Конечно, я должен иметь возможность десериализации массива в строго типизированный список.

Ответы [ 7 ]

29 голосов
/ 13 мая 2011

Если посмотреть на источник , то для WP7 Hammock фактически не использует Json.Net для анализа JSON. Вместо этого он использует собственный синтаксический анализатор, который не очень хорошо справляется с пользовательскими типами.

При непосредственном использовании Json.Net можно десериализовать в строго типизированную коллекцию внутри объекта-оболочки.

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();

и с:

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

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

Необходимость создания дополнительного объекта со свойством data раздражает, но это является следствием того, как создается объект в формате JSON.

Документация: Сериализация и десериализация JSON

11 голосов
/ 12 мая 2011

1001 * попробовать *

List<TheUser> friends = jsonSerializer.Deserialize<List<TheUser>>(response);
7 голосов
/ 18 января 2013

Это помогло мне десериализовать JSON в массив объектов:

List<TheUser> friends = JsonConvert.DeserializeObject<List<TheUser>>(response);
7 голосов
/ 09 августа 2012

Мне кажется, что это решение работает, и мне приходится кодировать кучу классов с данными в них.

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; }
}

Я должен был включить это для начала, вот пример метода, использующего выше:

public List<TheUser> GetUser()
{
    var results = GetUserJson();
    var userList = JsonConvert.DeserializeObject<DataResponse<TheUser>>(results.ToString());

    return userList.Data.ToList();
} 
6 голосов
/ 19 марта 2014

Json.NET - Документация

http://james.newtonking.com/json/help/index.html?topic=html/SelectToken.htm

Устный перевод для автора

var o = JObject.Parse(response);
var a = o.SelectToken("data").Select(jt => jt.ToObject<TheUser>()).ToList();
2 голосов
/ 13 мая 2011

Пэт, структура json выглядит очень знакомой для проблемы, которую я описал здесь - Ответ для меня заключался в том, чтобы рассматривать представление json как словарь, хотя там была только 1 запись.

Если я правильно, ваш ключ имеет тип string и значение List , где T представляет класс 'TheUser'

HTH

PS - если вы хотите улучшить сериализацию с помощью Silverlight Serializer , вам нужно будет создать версию WP7, бесстыдный плагин - я написал в блоге сообщение о этом

0 голосов
/ 13 мая 2011

Я подозреваю, что проблема в том, что json представляет объект со списком пользователей в качестве свойства.Попробуйте десериализовать что-то вроде:

public class UsersResponse
{
    public List<User> Data { get; set; }
}
...