web-dev-qa-db-fra.com

Problème de désérialisation avec DatacontractJsonSonSerializer

J'ai le morceau suivant de Json:

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

Tout en une ligne d'une ligne (adapté à un littéral à chaîne):

[{\"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.

Voici la classe que j'essaie 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 pour 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 se passe assez bien, sauf que items et rules sont vides pour le premier FooDef Pass. J'ai tout essayé sous le soleil pour essayer de les faire remplir: classes personnalisées, NameValueCollection, KeyValuePair<string, string>, List de ces derniers et toutes les autres collectes qui semblaient appliquer. [EDIT: J'ai oublié d'essayer Hashtable, qui semblait être un candidat évident. N'a pas fonctionné.]

Comme je le vois, le problème est que la pièce clé sous items et rules est ouverte. C'est-à-dire que cela ne va pas toujours être appelé range ou 3. Des conseils ou des idées?

22
bbrown

IMHO Il n'y a aucun moyen de désérialiser la chaîne JSON que vous avez fournie dans une classe .NET en utilisant DatacontractjsonSerializer.

Le problème vient de la manière DatacontractjsonSerializer sérialiser les dictionnaires. Vous pouvez utiliser un sérialisateur alternatif tel que JSON.NET (que je recommande vivement) ou Javascriptsérialiseur (Je pense que cela a été obsolète en faveur de DataContractJsonSonerializer, mais cela fonctionnera pour votre scénario ).

Vous pouvez également lire celles-cirants .

Documentation: Collections Serializing - JSON.net

22
Darin Dimitrov

http://social.msdn.microsoft.com/forums/en-us/wcf/thread/071f73bb-e141-4a68-ae61-05635382934f

Vérifiez cet article - il a résolu mon problème presque parfaitement. Je devais changer de type objet [] à une chaîne, mais je n'utilise que des chaînes: touches de type chaîne/paires de valeur, donc pas de problèmes là-bas.

7
Sean Kelly