web-dev-qa-db-fra.com

Désérialisation automatique des propriétés C # de JSON

J'ai besoin de désérialiser un objet JavaScript représenté en JSON dans une classe C # appropriée. Étant donné les caractéristiques intéressantes des propriétés automatiques, je préférerais les avoir dans ces classes plutôt que d'avoir simplement des champs. Malheureusement, le moteur de sérialisation .NET (au moins, par défaut) ignore totalement les propriétés automatiques sur la désérialisation et ne se soucie que du champ de support, qui n'est évidemment pas présent dans l'objet JavaScript.

Étant donné qu'il y a pas de manière standard de nommer les champs de sauvegarde et pour être honnête, je ne veux même pas m'embêter avec l'approche "Créons un objet JavaScript qui semble avoir des champs de sauvegarde C #" un peu sale, la seule façon de sérialiser des champs JavaScript en propriétés automatiques C # si je pouvais forcer le moteur de sérialisation à ignorer le champ de sauvegarde et utiliser directement la propriété. Malheureusement, je ne peux pas comprendre comment cela se fait ou si cela peut être fait du tout. Toute idée serait appréciée.

[~ # ~] modifier [~ # ~] : Voici un exemple:

Javascript:

function Cat()
{
    this.Name = "Whiskers";
    this.Breed = "Tabby";
}
var cat = new Cat();

Il est ensuite sérialisé en "{Name: 'Whiskers'}".

La classe C #:

[Serializable()]
public class Cat
{
    public string Name { get; set; }
    public string Breed { get; set; }
}

Et le code de désérialisation, qui échoue:

new DataContractJsonSerializer(typeof(Cat)).ReadObject(inputStream);

Et il ressort de l'exception qu'il échoue car il recherche le champ de support.

EDIT2 : Voici l'exception, si cela aide (pas d'exceptions internes):

System.Runtime.Serialization.SerializationException

"Le type de contrat de données 'Test.Cat' ne peut pas être désérialisé car les membres de données requis '<Name>k__BackingField, <Breed>k__BackingField 'est introuvable. "

50
Tamas Czinege

Ce qui se passe ici, c'est que le désérialiseur essaie de deviner le nom de vos champs de sauvegarde. Vous pouvez résoudre ce problème en ajoutant des mappages explicites (attributs DataContract/DataMember) comme ceci:

[DataContract]
public class Cat
{
    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public string Breed { get; set; }
}
80
baretta

Vous pouvez le faire avec JavaScriptSerializer dans le System.Web.Script.Serialization espace de noms:

JavaScriptSerializer serializer = new JavaScriptSerializer();
Cat c = serializer.Deserialize<Cat>(jsonString);

J'ai des objets POCO avec des propriétés automatiques et cela fonctionne très bien.

EDIT: J'ai écrit sur Sérialiseurs JSON en .NET qui compare ce sérialiseur avec DataContractJsonSerializer.

20
aleemb

réponse de baretta a résolu le ballonnement k__BackingField pour moi. Juste un petit addenda que vous pouvez décorer cette classe pour sérialiser automatiquement en XML ou JSON d'une manière similaire:

[Serializable, XmlRoot, DataContract]
public class Cat
{
  [XmlElement]
  [DataMember]
  public string Name { get; set; }
  [XmlElement]
  [DataMember]
  public string Breed { get; set; }
}

... puis utilisez un DataContractJsonSerializer ou XmlSerializer pour le préparer pour votre point de terminaison.

5
amelvin

Je suppose que vous transmettez des données via un service Web. Si vous utilisez la classe WebService avec l'attribut ScriptMethod sans commentaire, les méthodes du service Web peuvent lire JSON en mode natif. Ils utilisent même le même JavaScriptSerializer que celui mentionné ci-dessus. Si vous utilisez WCF, je suis un peu plus flou sur la logique.

Mais assurez-vous que votre objet JSON renvoie des données pour CHAQUE propriété de votre classe. Dans votre erreur, il est fait mention d'une propriété de race qui n'est pas dans votre exemple.

De plus, du côté de JavaScript, compte tenu de la nature dynamique de JavaScript, il est facile d'ajouter de nouvelles propriétés à vos objets. Cela peut parfois conduire à des références circulaires. Vous devez supprimer toutes les données supplémentaires que vous pourriez avoir ajoutées (tout comme vous envoyez des données via la méthode Web, puis les ajouter à nouveau une fois que vous avez terminé).

1
Chris Brandsma