Usando JsonConvert.DeserializeObject para deserializar Json a una clase C # POCO

Aquí está mi clase simple de User 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; } } 

Y el método que estoy usando para deserializar una respuesta JSON en un objeto User (esta llamada JSON real está aquí ):

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

Esto dispara una excepción:

No se puede deserializar el objeto JSON actual (por ejemplo, {“nombre”: “valor”}) en el tipo ‘System.Collections.Generic.List`1 [CoderwallDotNet.Api.Models.Account]’ porque el tipo requiere una matriz JSON (por ejemplo [ 1,2,3]) para deserializar correctamente.

Para corregir este error, cambie JSON a una matriz JSON (por ejemplo, [1,2,3]) o cambie el tipo deserializado para que sea un tipo .NET normal (p. Ej., No un tipo primitivo como entero, no un tipo de colección como una matriz o Lista) que se puede deserializar de un objeto JSON. JsonObjectAttribute también se puede agregar al tipo para forzarlo a deserializar desde un objeto JSON. Ruta ‘accounts.github’, línea 1, posición 129.

Como nunca antes había trabajado con este método DeserializeObject, estoy algo atrapado aquí.

Me he asegurado de que los nombres de las propiedades en la clase POCO sean los mismos que los nombres en la respuesta JSON.

¿Qué puedo intentar deserializar a JSON en esta clase de POCO?

Aquí hay un ejemplo de trabajo.

Los puntos clave son:

  • Declaración de Accounts
  • Uso del atributo 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; } 

Podría crear un JsonConverter . Vea aquí un ejemplo que es similar a su pregunta.

Otro enfoque, más sencillo, para deserializar una cadena JSON en camello a un objeto POCO con casquete pascal es usar CamelCasePropertyNamesContractResolver .

Es parte del espacio de nombres de Newtonsoft.Json.Serialization. Este enfoque supone que la única diferencia entre el objeto JSON y el POCO reside en la carcasa de los nombres de las propiedades. Si los nombres de las propiedades se deletrean de manera diferente, entonces deberá recurrir al uso de los atributos de JsonProperty para mapear los nombres de las propiedades.

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

La propiedad de cuentas se define así:

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

Su POCO declara esto:

 public List Accounts { get; set; } 

Intenta usar este Json:

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

Una serie de elementos (que se asignará a la lista) siempre se incluye entre corchetes.

Editar: La Cuenta Poco será algo como esto:

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

y tal vez otras propiedades.

Editar 2: para no tener una matriz, use la propiedad de la siguiente manera:

 public Account Accounts { get; set; } 

con algo así como la clase de muestra que publiqué en la primera edición.

 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.` 

El mensaje completo indica que es posible serializar a un objeto List, pero la entrada debe ser una lista JSON. Esto significa que su JSON debe contener

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

Donde los datos de AccountObject son JSON que representan su objeto Account o su objeto Badge

Lo que parece estar recibiendo actualmente es

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

Donde cuentas es un objeto JSON (indicado por llaves), no una matriz de objetos JSON (las matrices se indican con corchetes), que es lo que desea. Tratar

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

En la línea de la respuesta aceptada, si tiene una muestra de texto JSON, puede conectarla a este convertidor , seleccionar sus opciones y generar el código C #.

Si no conoce el tipo en tiempo de ejecución, este tema parece encajar.

deserializar dinámicamente json en cualquier objeto pasado. c #

Eso no es exactamente lo que tenía en mente. ¿Qué haces si tienes un tipo genérico para que solo se conozca en tiempo de ejecución?

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