Использование JsonConvert.DeserializeObject для десериализации Json в class C # POCO

Вот мой простой User class POCO:

 ///  /// The User class represents a Coderwall User. ///  public class User { ///  /// A User's username. eg: "sergiotapia, mrkibbles, matumbo" ///  public string Username { get; set; } ///  /// A User's name. eg: "Sergio Tapia, John Cosack, Lucy McMillan" ///  public string Name { get; set; } ///  /// A User's location. eh: "Bolivia, USA, France, Italy" ///  public string Location { get; set; } public int Endorsements { get; set; } //Todo. public string Team { get; set; } //Todo. ///  /// A collection of the User's linked accounts. ///  public List Accounts { get; set; } ///  /// A collection of the User's awarded badges. ///  public List Badges { get; set; } } 

И метод, который я использую для десериализации ответа JSON в объект User (этот фактический вызов JSON здесь ):

 private User LoadUserFromJson(string response) { var outObject = JsonConvert.DeserializeObject(response); return outObject; } 

Это вызывает исключение:

Невозможно десериализовать текущий объект JSON (например, {“name”: “value”}) в тип ‘System.Collections.Generic.List`1 [CoderwallDotNet.Api.Models.Account]’, потому что для типа требуется массив JSON (например, [ 1,2,3]) для десериализации.

Чтобы исправить эту ошибку, либо измените JSON на массив JSON (например, [1,2,3]), либо измените десериализованный тип, чтобы он был обычным типом .NET (например, не примитивным типом типа integer, а не типом коллекции, например массив или список), которые можно десериализовать из объекта JSON. JsonObjectAttribute также можно добавить к типу, чтобы заставить его десериализовать объект JSON. Путь «accounts.github», строка 1, позиция 129.

Никогда ранее не работая с этим методом DeserializeObject, я как бы застрял здесь.

Я убедился, что имена свойств в classе POCO совпадают с именами в ответе JSON.

Что я могу попытаться десериализовать JSON в этом classе POCO?

Вот рабочий пример.

Ключевые точки:

  • Декларация Accounts
  • Использование атрибута JsonProperty

,

 using (WebClient wc = new WebClient()) { var json = wc.DownloadString("http://coderwall.com/mdeiters.json"); var user = JsonConvert.DeserializeObject(json); } 

 public class User { ///  /// A User's username. eg: "sergiotapia, mrkibbles, matumbo" ///  [JsonProperty("username")] public string Username { get; set; } ///  /// A User's name. eg: "Sergio Tapia, John Cosack, Lucy McMillan" ///  [JsonProperty("name")] public string Name { get; set; } ///  /// A User's location. eh: "Bolivia, USA, France, Italy" ///  [JsonProperty("location")] public string Location { get; set; } [JsonProperty("endorsements")] public int Endorsements { get; set; } //Todo. [JsonProperty("team")] public string Team { get; set; } //Todo. ///  /// A collection of the User's linked accounts. ///  [JsonProperty("accounts")] public Account Accounts { get; set; } ///  /// A collection of the User's awarded badges. ///  [JsonProperty("badges")] public List Badges { get; set; } } public class Account { public string github; } public class Badge { [JsonProperty("name")] public string Name; [JsonProperty("description")] public string Description; [JsonProperty("created")] public string Created; [JsonProperty("badge")] public string BadgeUrl; } 

Вы можете создать JsonConverter . См. Здесь пример, похожий на ваш вопрос.

Другой, более оптимизированный подход к десериализации строки JSON с верблюжьей оболочкой в ​​объект POCO с параболическим обложением – это использование CamelCasePropertyNamesContractResolver .

Это часть пространства имен Newtonsoft.Json.Serialization. Этот подход предполагает, что единственная разница между объектом JSON и POCO заключается в оболочке имен свойств. Если имена свойств пишутся по-разному, вам нужно прибегнуть к использованию атрибутов JsonProperty для отображения имен свойств.

 using Newtonsoft.Json; using Newtonsoft.Json.Serialization; . . . private User LoadUserFromJson(string response) { JsonSerializerSettings serSettings = new JsonSerializerSettings(); serSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); User outObject = JsonConvert.DeserializeObject(jsonValue, serSettings); return outObject; } 

Свойство учетных записей определяется следующим образом:

 "accounts":{"github":"sergiotapia"} 

В вашем POCO указано следующее:

 public List Accounts { get; set; } 

Попробуйте использовать этот Json:

 "accounts":[{"github":"sergiotapia"}] 

Массив элементов (который будет отображаться в списке) всегда заключен в квадратные скобки.

Изменить: учетная запись Poco будет выглядеть примерно так:

 class Account { public string github { get; set; } } 

и, возможно, другие свойства.

Изменить 2: Чтобы не иметь массив, используйте свойство следующим образом:

 public Account Accounts { get; set; } 

с чем-то вроде classа образца, который я опубликовал в первом редактировании.

 to fix this error either change the JSON to a JSON array (eg [1,2,3]) or change the deserialized type so that it is a normal .NET type (eg not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object.` 

Все сообщение указывает, что можно сериализовать объект List, но вход должен быть списком JSON. Это означает, что ваш JSON должен содержать

 "accounts" : [{}...], 

Где данные AccountObject – это JSON, представляющий объект вашей учетной записи или объект значка

Кажется, что в настоящее время

 "accounts":{"github":"sergiotapia"} 

Где учетные записи являются объектами JSON (обозначаются фигурными скобками), а не массивом объектов JSON (массивы обозначаются скобками), что вам и нужно. Пытаться

 "accounts" : [{"github":"sergiotapia"}] 

В соответствии с принятым ответом, если у вас есть образец текста JSON, вы можете подключить его к этому конвертеру , выбрать свои параметры и сгенерировать код C #.

Если вы не знаете тип во время выполнения, этот вопрос выглядит так, как будто он подходит.

динамически десериализовать json в любой объект, переданный в. c #

Это не совсем то, что я имел в виду. Что вы будете делать, если у вас есть общий тип, который будет известен только во время выполнения?

 public MyDTO toObject() { try { var methodInfo = MethodBase.GetCurrentMethod(); if (methodInfo.DeclaringType != null) { var fullName = methodInfo.DeclaringType.FullName + "." + this.dtoName; Type type = Type.GetType(fullName); if (type != null) { var obj = JsonConvert.DeserializeObject(payload); //var obj = JsonConvert.DeserializeObject(payload); // <--- type ????? ... } } // Example for java.. Convert this to C# return JSONUtil.fromJSON(payload, Class.forName(dtoName, false, getClass().getClassLoader())); } catch (Exception ex) { throw new ReflectInsightException(MethodBase.GetCurrentMethod().Name, ex); } } 
  • Deserialize JSON в динамический объект C #?
  • Сериализация типа Json.Net с полиморфным дочерним объектом
  • XSLT: как преобразовать XML-узел в строку
  • gwt - Использование списка в вызове RPC?
  • Невозможно десериализовать lambda
  • «Тип не ожидается», используя DataContractSerializer - но это просто class, не смешные вещи?
  • Задача не сериализуема: java.io.NotSerializableException при вызове функции закрытие только для classов не объектов
  • Удаление десериализации JSON в объект с помощью Json.NET
  • Использование readObject / writeObject в сериализации
  • Рекомендации по сериализации DateTime в .NET 3.5
  • Json Сериализация Java, которая работает с GWT
  • Давайте будем гением компьютера.