2009-02-27 10 views
22

J'ai la pièce suivante de JSON:problème Désérialisation avec 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:" 
}] 

Dans une version en ligne (adaptée pour une chaîne littérale):

[{\"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:\"}] 

Dans l'exemple ci-dessus, name , value et label sont requis, mais items et rules sont facultatifs.

est ici la classe que je suis en train de désérialiser dans:

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; } 
    } 
} 

Voici le code que j'utilise désérialiser:

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(); 

Tout va assez bien, sauf que items et rules sont vides pour la premier FooDef passer. J'ai tout essayé sous le soleil pour essayer de les peupler: classes personnalisées, NameValueCollection, KeyValuePair<string, string>, List de ces deux derniers, et toutes les autres collections qui semblaient s'appliquer. [EDIT: J'ai oublié d'essayer Hashtable, qui semblait être un candidat évident. N'a pas fonctionné.]

Le problème, comme je le vois, est que la pièce maîtresse sous items et rules est ouverte. Autrement dit, il ne sera pas toujours appelé range ou 3. Des conseils ou des idées?

Répondre

21

IMHO Il n'existe aucun moyen de désérialiser la chaîne JSON que vous avez fournie dans une classe .NET à l'aide de DataContractJsonSerializer.

Le problème provient de la façon dont DataContractJsonSerializer sérialise les dictionnaires. Vous pouvez utiliser un sérialiseur alternatif tel que Json.NET (que je recommande fortement) ou JavaScriptSerializer (je pense qu'il était déconseillé en faveur de DataContractJsonSerializer mais cela fonctionnera pour votre scénario). Vous pouvez également lire theserants.

Documentation: Serializing Collections - Json.NET

+0

C'est un peu ce que je craignais. J'évitais de passer à JavaScriptSerializer à cause de la dépréciation, mais je suis heureux d'apprendre qu'il n'était pas sous-estimé dans 3.5 SP1. Je vais essayer en utilisant cette classe. – bbrown

+1

Je l'ai essayé avec JavaScriptSerializer et cela a fonctionné parfaitement. J'ai fini par utiliser Dictionary mais Hashtable a aussi fonctionné. – bbrown

+2

+1 pour Json.NET –

Questions connexes