2009-02-27 11 views
22

Mam następujący fragment z JSON:Deserializacji problem z 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:" 
}] 

Wszystko w jednym wersja linia (nadaje się do łańcucha dosłownym):

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

w powyższym przykładzie, name , value i label są wymagane, ale items i rules są opcjonalne.

Oto klasa Próbuję deserializowania do:

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

Oto kod używam do deserializowania:

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

Wszystko idzie dość dobrze z wyjątkiem, że items i rules są puste dla pierwsza przepustka FooDef. Próbowałem wszystkiego, co było pod słońcem, próbując je zapełnić: niestandardowe klasy, NameValueCollection, KeyValuePair<string, string>, List zarówno tych ostatnich, jak i wszystkich innych kolekcji, które wydawały się mieć zastosowanie. [EDIT: Zapomniałem spróbować Hashtable, co wydawało się oczywistym kandydatem. Nie działa.]

Problem, jak widzę, polega na tym, że kluczowy element pod numerem items i rules jest otwarty. Oznacza to, że nie zawsze będzie to nazywane range lub 3. Wszelkie porady lub pomysły?

Odpowiedz

21

IMHO nie ma możliwości deserializacji łańcucha znaków JSON podanego w klasie .NET za pomocą DataContractJsonSerializer.

Problem wynika ze sposobu serializowania słowników w postaci DataContractJsonSerializer. Możesz użyć alternatywnego serializera, takiego jak Json.NET (który gorąco polecam) lub JavaScriptSerializer (myślę, że został on przestarzały na rzecz DataContractJsonSerializer, ale będzie działać w twoim scenariuszu).

Można również przeczytać theserants.

Dokumentacja: Serializing Collections - Json.NET

+0

Tego właśnie się obawiałem. Unikałem przełączania się na JavaScriptSerializer ze względu na wycofanie, ale cieszę się, że zostało ono niezatwierdzone w wersji 3.5 SP1. Spróbuję użyć tej klasy. – bbrown

+1

Próbowałem go z JavaScriptSerializer i działało idealnie. Skończyło się na użyciu Dictionary , ale Hashtable również działała. – bbrown

+2

+1 dla Json.NET –

Powiązane problemy