2009-02-27 18 views
22

Ho il seguente pezzo di JSON:problema deserializzazione con DataContractJsonSerializer

[{ 
    "name": "numToRetrieve", 
    "value": "3", 
    "label": "Number of items to retrieve:", 
    "items": { 
     "1": "1", 
     "3": "3", 
     "5": "5" 
    }, 
    "rules": { 
     "range": "1-2" 
    } 
}, 
{ 
    "name": "showFoo", 
    "value": "on", 
    "label": "Show foo?" 
}, 
{ 
    "name": "title", 
    "value": "Foo", 
    "label": "Foo:" 
}] 

Tutto in una versione a linea (adatto per una stringa letterale):

[{\"name\":\"numToRetrieve\",\"value\":\"3\",\"label\":\"Number of items to retrieve:\",\"items\":{\"1\":\"1\",\"3\":\"3\",\"5\":\"5\"},\"rules\":{\"range\":\"1-2\"}},{\"name\":\"showFoo\",\"value\":\"on\",\"label\":\"Show foo?\"},{\"name\":\"title\",\"value\":\"Foo\",\"label\":\"Foo:\"}] 

Nell'esempio di cui sopra, name , value e label sono richiesti ma items e rules sono facoltativi.

Ecco la classe che sto cercando di deserializzare in:

using System.Collections; 
using System.Collections.Generic; 
using System.Runtime.Serialization; 

namespace foofoo 
{ 
    [DataContract] 
    public sealed class FooDef 
    { 
     [DataMember(Name = "name", IsRequired = true)] 
     public string Name { get; set; } 

     [DataMember(Name = "value", IsRequired = true)] 
     public string Value { get; set; } 

     [DataMember(Name = "label", IsRequired = true)] 
     public string Label { get; set; } 

     [DataMember(Name = "items", IsRequired = false)] 
     public Dictionary<string, string> Items { get; set; } 

     [DataMember(Name = "rules", IsRequired = false)] 
     public Dictionary<string, string> Rules { get; set; } 
    } 
} 

Ecco il codice che uso per deserializzare:

var json = new DataContractJsonSerializer(typeof(List<FooDef>)); 
var bar = "[{\"name\":\"numToRetrieve\",\"value\":\"3\",\"label\":\"Number of items to retrieve:\",\"items\":{\"1\":\"1\",\"3\":\"3\",\"5\":\"5\"},\"rules\":{\"range\":\"1-2\"}},{\"name\":\"showFoo\",\"value\":\"on\",\"label\":\"Show foo?\"},{\"name\":\"title\",\"value\":\"Foo\",\"label\":\"Foo:\"}]"; 
var stream = new MemoryStream(Encoding.UTF8.GetBytes(bar)); 
var foo = json.ReadObject(stream); 
stream.Close(); 

Tutto va abbastanza bene, tranne che items e rules sono vuoti per la primo passaggio FooDef. Ho provato tutto sotto il sole per cercare di farli popolarsi: classi personalizzate, NameValueCollection, KeyValuePair<string, string>, List di entrambi, e ogni altra raccolta che sembrava applicare. [EDIT: ho dimenticato di provare Hashtable, che sembrava un candidato ovvio. Non ha funzionato.]

Il problema, a mio avviso, è che la chiave sotto items e rules è aperta. Cioè, non sarà sempre chiamato range o 3. Qualche consiglio o idea?

risposta

21

IMHO non è possibile deserializzare la stringa JSON fornita in una classe .NET utilizzando DataContractJsonSerializer.

Il problema deriva dal modo in cui i dizionari serializza DataContractJsonSerializer. È possibile utilizzare un serializzatore alternativo come Json.NET (che consiglio vivamente) o JavaScriptSerializer (penso sia stato deprecato in favore di DataContractJsonSerializer ma funzionerà per lo scenario).

È anche possibile leggere theserants.

Documentazione: Serializing Collections - Json.NET

+0

Questo è un po 'quello che temevo. Stavo evitando di passare a JavaScriptSerializer a causa della deprecazione, ma sono lieto di sapere che è stato sottovalutato in 3.5 SP1. Lo proverò usando quella classe. – bbrown

+1

L'ho provato con JavaScriptSerializer e ha funzionato perfettamente. Ho finito per usare Dictionary ma anche Hashtable ha funzionato. – bbrown

+2

+1 per Json.NET –

Problemi correlati