2010-11-07 7 views
0

J'essaie de désérialiser la chaîne JSON en dictionnaire observable. Si j'utilise le dictionnaire générique normal à partir de .NET, il fonctionne bien, mais si je tente d'utiliser mon propre dictionnaire observable i obtenir exception:Désérialise JSON avec JSON.NET en dictionnaire observable [C#]

La clé donnée était présent dans le dictionnaire.

StackTrace:

à System.Collections.Generic.Dictionary 2.get_Item(TKey key) at ObservableDictionary.MyObservableDictionary 2.set_Item (clé TKey, valeur TValue) dans C: \ Users \ Jan \ Documents \ Visual Studio 2010 \ Projects \ PokecMessanger-bonne version - Copie \ ObservableDictionary \ MyObservableDictionary.cs: ligne 163 à Newtonsoft.Json.Utilities.DictionaryWrapper`2.System.Collections.IDictionary.set_Item (Clé de l'objet, Valeur de l'objet) dans d: \ Development \ Releases \ Json \ Working \ Src \ Newtonsoft.Json \ Utilities \ DictionaryWrapper.cs: ligne 353

Observable classe dictionnaire:

public class MyObservableDictionary<TKey, TValue> : 
    IDictionary<TKey, TValue>, 
    INotifyCollectionChanged, 
    INotifyPropertyChanged 
{ 
    private readonly IDictionary<TKey, TValue> _dictionary = new Dictionary<TKey, TValue>(); 

    #region Implementation of INotifyCollectionChanged 

    public event NotifyCollectionChangedEventHandler CollectionChanged; 

    #endregion 

    #region Implementation of INotifyPropertyChanged 

    public event PropertyChangedEventHandler PropertyChanged; 

    #endregion 

    #region Implementation of IEnumerable 

    public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() 
    { 
     return _dictionary.GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 

    #endregion 

    #region Implementation of ICollection<KeyValuePair<TKey,TValue>> 

    public void Add(KeyValuePair<TKey, TValue> item) 
    { 
     _dictionary.Add(item); 
     if (CollectionChanged != null) 
      CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add)); 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs("Keys")); 
      PropertyChanged(this, new PropertyChangedEventArgs("Values")); 
     } 

    } 

    public void Clear() 
    { 
     int keysCount = _dictionary.Keys.Count; 

     _dictionary.Clear(); 

     if (keysCount == 0) return; 

     if (CollectionChanged != null) 
     { 
      CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 
     } 

     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs("Keys")); 
      PropertyChanged(this, new PropertyChangedEventArgs("Values")); 
     } 
    } 

    public bool Contains(KeyValuePair<TKey, TValue> item) 
    { 
     return _dictionary.Contains(item); 
    } 

    public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) 
    { 
     _dictionary.CopyTo(array, arrayIndex); 
    } 

    public bool Remove(KeyValuePair<TKey, TValue> item) 
    { 
     bool remove = _dictionary.Remove(item); 

     if (!remove) return false; 

     if (CollectionChanged != null) 
      CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove)); 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs("Keys")); 
      PropertyChanged(this, new PropertyChangedEventArgs("Value")); 
     } 
     return true; 
    } 

    public int Count 
    { 
     get { return _dictionary.Count; } 
    } 

    public bool IsReadOnly 
    { 
     get { return _dictionary.IsReadOnly; } 
    } 

    #endregion 

    #region Implementation of IDictionary<TKey,TValue> 

    public bool ContainsKey(TKey key) 
    { 
     return _dictionary.ContainsKey(key); 
    } 

    public void Add(TKey key, TValue value) 
    { 
     _dictionary.Add(key, value); 

     if (CollectionChanged != null) 
      CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add)); 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs("Keys")); 
      PropertyChanged(this, new PropertyChangedEventArgs("Values")); 
     } 
    } 

    public bool Remove(TKey key) 
    { 
     bool remove = _dictionary.Remove(key); 

     if (!remove) return false; 

     if (CollectionChanged != null) 
      CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove)); 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs("Keys")); 
      PropertyChanged(this, new PropertyChangedEventArgs("Values")); 
     } 
     return true; 
    } 

    public bool TryGetValue(TKey key, out TValue value) 
    { 
     return _dictionary.TryGetValue(key, out value); 
    } 

    public TValue this[TKey key] 
    { 
     get { return _dictionary[key]; } 
     set 
     { 
      bool changed = _dictionary[key].Equals(value); 

      if (!changed) return; 
      _dictionary[key] = value; 

      if (CollectionChanged != null) 
       CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace)); 

      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs("Keys")); 
       PropertyChanged(this, new PropertyChangedEventArgs("Values")); 
      } 
     } 
    } 

    public ICollection<TKey> Keys 
    { 
     get { return _dictionary.Keys; } 
    } 

    public ICollection<TValue> Values 
    { 
     get { return _dictionary.Values; } 
    } 

    #endregion 
} 

look chaîne JSON comme ceci:

{ 
    "pepina888": { 
    "idUser": 3338870, 
    "nick": "pepina888", 
    "sefNick": "pepina888", 
    "status": 1, 
    "photo": "http:\/\/213.215.107.127\/fotky\/333\/88\/s_3338870.jpg?v=9", 
    "sex": 2, 
    "isFriend": 1 
    }, 
    "yayushka": { 
    "idUser": 5281019, 
    "nick": "YAYUSHKA", 
    "sefNick": "yayushka", 
    "status": 1, 
    "photo": "http:\/\/213.215.107.125\/fotky\/528\/10\/s_5281019.jpg?v=4", 
    "sex": 2, 
    "isFriend": 1 
    }, 
    "miska20258": { 
    "idUser": 11112713, 
    "nick": "miska20258", 
    "sefNick": "miska20258", 
    "status": 1, 
    "photo": "http:\/\/213.215.107.125\/fotky\/1111\/27\/s_11112713.jpg?v=6", 
    "sex": 2, 
    "isFriend": 1 
    }, 
    ... snip snip ... 
} 

Code Problème:

MyObservableDictionary<string, FriendData> friends = new MyObservableDictionary<string, FriendData>(); 
//problem is here 
friends = JsonConvert.DeserializeObject<MyObservableDictionary<string, FriendData>>(jsonString.ToString()); 

look classe ami comme ceci:

public class FriendData 
{ 
    public string idUser { get; set; } 
    public string nick { get; set; } 
    public string sefNick { get; set; } 
    public string status { get; set; } 
    public string photo { get; set; } 
    public string sex { get; set; } 
    public string isFriend { get; set; } 
    public BitmapImage profilePhoto { get; set; } 
    public ImageSource imageSource { get; set; } 
    public string blockQuote { get; set; } 

    public FriendData(string idUser, string nick, string sefNick, string status, string photo, string sex, string isFriend) 
    { 
     this.idUser = idUser; 
     this.nick = nick; 
     this.sefNick = sefNick; 
     this.status = status; 
     this.photo = photo; 
     this.sex = sex; 
     this.isFriend = isFriend; 
    } 
} 

S'il vous plaît, toute avance, je ne sais pas ce qui ne va pas. Je vous remercie. Sur la désérialisation, j'utilise JSON.NET.

À Jon Skeet: i essayer ce

public TValue this[TKey key] 
{ 
    get 
    { 
     if(TryGetValue(key)) 
      return _dictionary[key]; 
    } 

    set 
    { 
     bool changed = _dictionary[key].Equals(value); 
     if (!changed) return; 

     _dictionary[key] = value; 

     if (CollectionChanged != null) 
      CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace)); 

     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs("Keys")); 
      PropertyChanged(this, new PropertyChangedEventArgs("Values")); 
     } 
    } 
} 

Répondre

2

Le problème n'est pas JSON - c'est votre dictionnaire. Regardez ce code:

public TValue this[TKey key] 
{ 
    get { return _dictionary[key]; } 
    set 
    { 
     bool changed = _dictionary[key].Equals(value); 
     ... 
    } 
} 

Comment pensez-vous pouvoir toujours définir une valeur dans le dictionnaire? L'indexeur "get" lèvera une exception si la clé donnée n'est pas dans le dictionnaire.

Vous devez utiliser TryGetValue à la place, et ne vérifier l'égalité que si la clé était réellement présente en premier lieu.

Il est bon de noter que vous auriez pu trouver ce problème en testant un type de dictionnaire dans votre unité avant même d'essayer de l'utiliser dans le contexte de la désérialisation JSON.

EDIT: L'exception se produit dans le setter parce que vous essayez toujours d'accéder au getter du dictionnaire sous-jacent. Vous avez besoin d'être quelque chose comme ceci:

set 
{ 
    TValue existingValue; 
    if (_dictionary.TryGetValue(key, out existingValue)) 
    { 
     // We already have a value for this key. Check whether it's the same. 
     if (object.Equals(value, existingValue)) 
     { 
      return; 
     } 
    } 
    // Do the rest of your logic here. 
} 
+0

Je tente mais ça ne fonctionne pas, pouvez-vous me donner un exemple de code? merci – Joe

+0

@Joe: Oui, ça * fonctionne *. Veuillez montrer ce que vous avez essayé - éditez votre question en essayant de changer le dictionnaire. –

+0

Oui M.Skeet j'ai édité mon sujet. – Joe

Questions connexes