2009-06-03 8 views
49

Ho bisogno di deserializzare alcuni oggetti JavaScript rappresentati in JSON in una classe C# appropriata. Date le belle caratteristiche delle proprietà automatiche, preferirei averle in queste classi piuttosto che avere solo dei campi. Sfortunatamente, il motore di serializzazione .NET (almeno, per impostazione predefinita) ignora completamente le proprietà automatiche in fase di deserializzazione e si preoccupa solo del campo di supporto, che ovviamente non è presente nell'oggetto JavaScript.Deserializzazione proprietà C# automatica di JSON

Dato che c'è no standard way to name backing fields e, a dire il vero, non voglio nemmeno disturbarmi con l'approccio "creiamo un oggetto JavaScript che sembra avere campi di backing C#" dato che suona un po 'sporco, l'unico modo in cui potrei serializza i campi JavaScript per le proprietà automatiche di C# se potessi forzare il motore di serializzazione in qualche modo a ignorare il campo di supporto e utilizzare direttamente la proprietà. Sfortunatamente, non riesco a capire come è fatto o se è possibile farlo. Qualsiasi idea sarebbe apprezzata.

EDIT: Ecco un esempio:

Javascript:

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

Questo è poi serializzato in "{Nome: 'Whiskers'}".

Il C# classe:

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

E il codice deserializzazione, che non riesce:

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

ed è evidente dal l'eccezione che non riesce perché è alla ricerca per il campo di supporto.

EDIT2: Ecco l'eccezione, se questo aiuta (senza eccezioni interne):

System.Runtime.Serialization.SerializationException

"Il tipo di contratto di dati 'Test.Cat' non può essere deserializzato perché i membri di dati richiesti "<Name>k__BackingField, <Breed>k__BackingField" non sono stati trovati . "

+0

Puoi pubblicare un esempio di cosa intendi? –

+0

@John Saunders - diciamo che ho ottenuto un oggetto JavaScript chiamato "Cat" con un singolo campo chiamato "Nome" con il valore "Whiskers". Diciamo che questo è rappresentato in JSON. Voglio prendere questo JSON e serializzarlo su un'istanza della classe C# Cat (scritta da me) in modo che il processo di serializzazione compili la proprietà automatica "Nome" dell'istanza con "Whiskers". –

+0

... ma il problema è che il serializzatore sta cercando il campo di supporto (es. " k_backingField" ma non necessariamente con questo nome ") e non" Nome ". –

risposta

79

Quello che sta succedendo qui è il deserializzatore sta cercando di indovinare il nome dei campi backing. È possibile risolvere questo con l'aggiunta di mapping espliciti (attributi DataContract/DataMember) come questo:

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

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

+1 prima domanda che ho risposto, ma non ho avuto il rappresentante di upvote questa risposta, al momento! – amelvin

+2

Vorrei +2 se potessi. Cerchi la risposta a questo per un po 'ora. – Kelly

+0

super! Ho perso l'attributo [DataContract] :( – Ruutert

20

Si può fare questo con JavaScriptSerializer trovato nella System.Web.Script.Serialization namespace:

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

ho oggetti POCO con proprietà automatiche e questo funziona bene.

MODIFICA: Ho scritto su JSON Serializers in .NET che confronta questo serializzatore con DataContractJsonSerializer.

+0

Sì, sembra che sarò bloccato con il buon vecchio JsonExSerializer http://code.google.com/p/ jsonexserializer/ –

1

Suppongo che stiate passando dei dati tramite un servizio web. Se si utilizza la classe WebService con l'attributo ScriptMethod non commentato, i metodi del servizio Web possono leggere JSON in modo nativo. Usano anche lo stesso JavaScriptSerializer menzionato sopra. Se stai usando WCF sono un po 'più sfocato sulla logica.

Ma assicuratevi che il vostro oggetto JSON stia restituendo dati per OGNI proprietà nella vostra classe. Nel tuo errore, c'è menzione di una proprietà Breed che non è nel tuo esempio.

Inoltre, sul lato JavaScript, fare per la natura dinamica di JavaScript è facile aggiungere nuove proprietà agli oggetti. Questo a volte può portare a riferimenti circolari. Dovresti rimuovere tutti i dati aggiuntivi che potresti aver aggiunto (proprio come stai inviando i dati tramite il metodo web, quindi aggiungili di nuovo una volta che hai finito).

+0

No, sfortunatamente non si tratta di un servizio Web. È una semplice richiesta ajax che passa i dati in json al server. Sono abbastanza sicuro che non ci siano riferimenti circolari. Hai ragione che nell'esempio non ci sono proprietà di razza ma nel mio codice reale ci sono tutte le proprietà. Grazie per i suggerimenti però :) –

+0

Sul lato JavaScript delle cose: come stai convertendo l'oggetto JavaScript in JSON? –

+0

@ Chris Brandsma: Il solito modo, con json2.js: http://www.json.org/json2.js –

5

baretta's answer risolto il k__BackingField gonfiare per me. Basta un piccolo addendum che potete decorare questa classe di auto serializzare in XML o JSON in modo simile:

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

... e quindi utilizzare un DataContractJsonSerializer o XmlSerializer per prepararlo per il vostro punto finale.