2009-06-03 6 views
49

J'ai besoin de désérialiser certains objets JavaScript représentés dans 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 seulement des champs. Malheureusement, le moteur de sérialisation .NET (au moins, par défaut) ignore totalement les propriétés automatiques de désérialisation et se soucie uniquement du champ de sauvegarde, qui n'est évidemment pas présent dans l'objet JavaScript. Étant donné qu'il y a no standard way to name backing fields et pour être honnête, je ne veux même pas m'embêter avec l'approche «créons un objet JavaScript qui ressemble à des champs d'accompagnement C#», car cela semble un peu sale, la seule façon dont je pouvais sérialiser les champs JavaScript en auto-propriétés C# si je pouvais forcer le moteur de sérialisation à ignorer le champ de sauvegarde et à utiliser la propriété directement. Malheureusement, je ne peux pas comprendre comment cela est fait ou si cela peut être fait du tout. Toute idée serait appréciée.C# désérialisation automatique des propriétés de JSON

EDIT: Voici un exemple:

Javascript:

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

C'est alors sérialisé "{Nom: 'Moustaches'}".

La classe C#:

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

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

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

Et il ressort de l'exception qu'il échoue parce qu'il est à la recherche du champ de support.

EDIT2: Voici l'exception, si cela aide (sans exception): intérieure

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' n'ont pas été trouvés . "

+0

Pouvez-vous poster un exemple de ce que vous voulez dire? –

+0

@ John Saunders - Disons que j'ai un objet JavaScript appelé "Cat" avec un seul champ appelé "Nom" avec la valeur "Whiskers". Disons que ceci est représenté dans JSON. Je veux saisir ce JSON et le sérialiser vers une instance de classe C# Cat (écrite par moi) afin que le processus de sérialisation remplisse la propriété automatique "Nom" de l'instance avec "Whiskers". –

+0

... mais le problème est que le sérialiseur cherche le champ de sauvegarde (par exemple " k_backingField" mais pas nécessairement avec ce nom ") et non" Nom " –

Répondre

79

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 les correspondances explicites (DataContract/DataMember attributs) comme ceci:

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

    [DataMember] 
    public string Breed { get; set; } 
} 
+0

+1 Première question à laquelle j'ai répondu, mais je n'avais pas le représentant pour upvote cette réponse à l'époque! – amelvin

+2

Je ferais +2 si je pouvais. Vous cherchez la réponse à cela pour un peu maintenant. – Kelly

+0

super! J'ai raté l'attribut [DataContract] :( – Ruutert

20

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

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

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

EDIT: J'ai écrit environ JSON Serializers in .NET qui compare ce sérialiseur avec DataContractJsonSerializer.

+0

Oui, il semble que je serai coincé avec le bon vieux JsonExSerializer http://code.google.com/p/ jsonexserializer/ –

1

Je suppose que vous transmettez des données via un service Web. Si vous utilisez la classe WebService avec l'attribut ScriptMethod décommenté, les méthodes de service Web peuvent lire JSON de manière native. Ils utilisent même le même JavaScriptSerializer 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é Breed qui n'est pas dans votre exemple.

De même, du côté JavaScript, faites à 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 avez ajoutées (tout comme vous envoyez des données via la méthode Web, puis ajoutez-les à nouveau une fois que vous avez terminé).

+0

Non, malheureusement, ce n'est pas un service web, c'est une simple requête ajax qui transmet les données de json au serveur. Je suis à peu près sûr qu'il n'y a pas de références circulaires. Vous avez raison de dire que dans l'exemple il n'y a pas de propriété de race mais dans mon code réel toutes les propriétés sont là. Merci pour les suggestions cependant :) –

+0

Sur le côté JavaScript des choses: comment convertissez-vous l'objet JavaScript en JSON? –

+0

@Chris Brandsma: La manière habituelle, avec json2.js: http://www.json.org/json2.js –

5

baretta's answer résolu le k__BackingField ballonnement pour moi. Juste un petit supplément que vous pouvez décorer cette classe pour auto sérialisation 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 utiliser un DataContractJsonSerializer ou XmlSerializer pour préparer votre point final.

Questions connexes