2009-11-23 10 views
6

Następująca klasa nie przekształca się w postaci szeregowej (ale przekształca się w serializację) przy użyciu System.Web.Script.Serialization.JavaScriptSerializer.Nie można odserializować Nullewartowanej KeyValuePair z JSON z ASP.NET AJAX

public class foo { 
    public KeyValuePair<string, string>? bar {get;set;} 
} 

Próba deserializowania wyniki w System.NullReferenceException gdy System.Web.Script.Serialization.ObjectConverter.ConvertDictionaryToObject osiąga właściwość bar. (Uwaga: jest to przypuszczenie oparte na śledzeniu stosu.)

Zmiana typu właściwości na KeyValuePair<string,string> rozwiązuje problem, ale chciałbym zachować typ Nullable, jeśli to w ogóle możliwe.

JSON jest dokładnie to, czego można się spodziewać:

{"foo": { 
    "bar": { 
    "Key":"Jean-Luc", 
    "Value":"Picard" 
    } 
}} 

Pomoc?

+0

Deserializacja dla KeyValuePair nie naprawia powyższego błędu, ale w rzeczywistości powoduje dwa puste ciągi dla pary. tj. deserializacja powoduje utratę danych. Tak więc powyższy JSON zamienia się w KeyValue Pair z [,]! – Noel

Odpowiedz

4

Powodem tego jest to, że gdy JavaScriptSerializer próbuje deserializować, utworzy nowe wystąpienie klasy (w tym KeyValuePair), a następnie przypisze wartości do właściwości.

Powoduje to problem, ponieważ KeyValuePair może mieć tylko klucz i wartości przypisane jako część konstruktora, a nie przez właściwości, co skutkuje pustym kluczem i wartością.

Będzie można rozwiązać ten problem i problem pusty, tworząc klasę, która implementuje JavaScriptConverter i Registering It. Użyłem poniższego kodu do obsługi standardowej KeyValuePair, ale jestem pewien, że możesz go rozszerzyć, aby obsługiwać wartości null.

public class DictionaryJavaScriptConverter<k, v> : JavaScriptConverter 
{ 

    public override object Deserialize(System.Collections.Generic.IDictionary<string, object> dictionary, System.Type type, System.Web.Script.Serialization.JavaScriptSerializer serializer) 
    { 
     return new KeyValuePair<k, v>((k)dictionary["Key"], (v)dictionary["Value"]); 
    } 

    public override System.Collections.Generic.IDictionary<string, object> Serialize(object obj, System.Web.Script.Serialization.JavaScriptSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 

    public override System.Collections.Generic.IEnumerable<System.Type> SupportedTypes { 
     get { return new System.Type[] { typeof(KeyValuePair<k, v>) }; } 
    } 
} 

Alternatywnie można utworzyć prostą klasę, która ma dwie właściwości klucz i wartość.

+0

Dzięki za odpowiedź. Przez jakiś czas zmagałem się z tym problemem i nie mogłem się domyślić, dlaczego każdy inny typ danych będzie działał, ale nie KeyValuePair. Ponownie, dzięki, była to prosta i bardzo pomocna odpowiedź. – PetrolMan

+1

Zastanawiam się, w kontekście MVC 3: Czy istnieje sposób na zarejestrowanie tego konwertera tak, aby wszystkie wiązania modelu JSON miały dostęp do tego konwertera? Zarejestrowanie konwertera z konkretnym wystąpieniem JavaScriptSerializer nie pasuje do modelu MVC 3. – kdawg