En Utilisant JsonConvert.DeserializeObject pour désérialiser Json en C# POCO classe

Voici mon simple User classe POCO:

/// <summary>
/// The User class represents a Coderwall User.
/// </summary>
public class User
{
    /// <summary>
    /// A User's username. eg: "sergiotapia, mrkibbles, matumbo"
    /// </summary>
    public string Username { get; set; }

    /// <summary>
    /// A User's name. eg: "Sergio Tapia, John Cosack, Lucy McMillan"
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// A User's location. eh: "Bolivia, USA, France, Italy"
    /// </summary>
    public string Location { get; set; }

    public int Endorsements { get; set; } //Todo.
    public string Team { get; set; } //Todo.

    /// <summary>
    /// A collection of the User's linked accounts.
    /// </summary>
    public List<Account> Accounts { get; set; }

    /// <summary>
    /// A collection of the User's awarded badges.
    /// </summary>
    public List<Badge> Badges { get; set; }

}

et la méthode que j'utilise pour désérialiser une réponse JSON en un objet User (cet appel réel est ici ):

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

this fire an exception:

ne peut pas desérialiser l'objet JSON actuel (par exemple {"name": "Valeur"}) dans le type 'Système.Collection.Générique.Liste ' 1[CoderwallDotNet.API.Modèle.Compte'] parce que le type nécessite un tableau JSON (e.g. [1,2,3]) pour désérialiser correctement.

pour corriger cette erreur, changez le JSON en tableau JSON. (p.ex. [1,2,3]) ou changer le type désérialisé pour qu'il soit normal Type .NET (par exemple pas un type primitif comme un entier, pas une collection type comme un tableau ou une liste) qui peut être désérialisé à partir D'un JSON objet. JsonObjectAttribute peut aussi être ajouté au type pour le forcer désérialiser à partir d'un objet JSON. Chemin des comptes.github', ligne 1, poste 129.

N'ayant jamais travaillé avec cette méthode DeserializeObject avant, je suis un peu coincé ici.

j'ai fait en sorte que les noms de propriétés dans la classe POCO soient les mêmes que les noms dans la réponse JSON.

Qu'est-ce que je peux essayer de desérialiser JSON dans cette classe de POCO?

49
demandé sur Only Bolivian Here 2012-06-20 22:52:19

7 réponses

voici un exemple pratique.

les points clés sont:

  • déclaration de Accounts
  • utilisation de JsonProperty attribut

.

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

-

public class User
{
    /// <summary>
    /// A User's username. eg: "sergiotapia, mrkibbles, matumbo"
    /// </summary>
    [JsonProperty("username")]
    public string Username { get; set; }

    /// <summary>
    /// A User's name. eg: "Sergio Tapia, John Cosack, Lucy McMillan"
    /// </summary>
    [JsonProperty("name")]
    public string Name { get; set; }

    /// <summary>
    /// A User's location. eh: "Bolivia, USA, France, Italy"
    /// </summary>
    [JsonProperty("location")]
    public string Location { get; set; }

    [JsonProperty("endorsements")]
    public int Endorsements { get; set; } //Todo.

    [JsonProperty("team")]
    public string Team { get; set; } //Todo.

    /// <summary>
    /// A collection of the User's linked accounts.
    /// </summary>
    [JsonProperty("accounts")]
    public Account Accounts { get; set; }

    /// <summary>
    /// A collection of the User's awarded badges.
    /// </summary>
    [JsonProperty("badges")]
    public List<Badge> 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;
}
80
répondu L.B 2012-06-20 20:12:34

Vous pouvez créer un JsonConverter . Voir ici pour un exemple similaire à votre question.

4
répondu SwDevMan81 2017-05-23 12:34:32

une autre méthode, plus simple et plus simple, de desérialiser une chaîne de caractères JSON à base de chameaux vers un objet POCO à base de pascal consiste à utiliser le CamelCasePropertyNamesContractResolver .

ça fait partie du Newtonsoft.Json.Namespace de sérialisation. Cette approche suppose que la seule différence entre l'objet JSON et le POCO réside dans le cadrage des noms de propriété. Si la propriété noms sont orthographiés différemment, alors vous aurez besoin de recourir à utiliser les attributs JsonProperty pour cartographier les noms de propriétés.

using Newtonsoft.Json; 
using Newtonsoft.Json.Serialization;

. . .

private User LoadUserFromJson(string response) 
{
    JsonSerializerSettings serSettings = new JsonSerializerSettings();
    serSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    User outObject = JsonConvert.DeserializeObject<User>(jsonValue, serSettings);

    return outObject; 
}
4
répondu John Iwasz 2014-12-19 22:05:46

la propriété accounts est définie comme ceci:

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

votre POCO déclare ceci:

public List<Account> Accounts { get; set; }

essayez d'utiliser ce Json:

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

Un tableau d'éléments (qui va être mappé à la liste) est toujours entre crochets.

Edit: Le Compte Poco sera quelque chose comme ceci:

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

et peut-être d'autres propriété.

Edit 2: De ne pas avoir un tableau utiliser la propriété comme suit:

public Account Accounts { get; set; }

avec quelque chose comme la classe échantillon que j'ai posté dans la première édition.

3
répondu Sascha 2012-06-20 18:59:41
to fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the
deserialized type so that it is a normal .NET type (e.g. not a primitive type like
integer, not a collection type like an array or List) that can be deserialized from a
JSON object.`

le message entier indique qu'il est possible de sérialiser vers un objet List, mais l'entrée doit être une liste JSON. Cela signifie que votre JSON doit contenir

"accounts" : [{<AccountObjectData}, {<AccountObjectData>}...],

où les données D'objet de compte sont JSON représentant votre objet de Compte ou votre objet de Badge

ce qu'il semble obtenir actuellement est

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

où accounts est un objet JSON (indiqué par des accolades bouclées), pas un tableau de Les objets JSON (les tableaux sont désignés par des parenthèses), ce qui est ce que vous voulez. Essayez

"accounts" : [{"github":"sergiotapia"}]
2
répondu dmi_ 2012-06-20 19:09:03

dans la lignée de la réponse acceptée, si vous avez un échantillon de texte JSON vous pouvez le brancher à ce convertisseur , sélectionnez vos options et générez le code C#.

si vous ne connaissez pas le type à l'exécution, ce sujet semble adapté.

désérialiser dynamiquement json dans n'importe quel objet passé. c#

1
répondu Jim 2017-05-23 11:47:04

ce n'est pas exactement ce que j'avais en tête. Que faites-vous si vous avez un type générique à être connue au moment de l'exécution?

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<type.MemberType.GetType()>(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);
  }
}
0
répondu Latency 2015-02-26 18:41:48