2010-11-07 58 views
0

我嘗試將JSON字符串反序列化爲可觀察字典。如果我正常使用通用字典從.NET它的作品不錯,但如果我嘗試用我自己觀察到的字典,我得到異常:將JSON.NET反序列化爲可觀察字典[C#]

給定的關鍵是不存在的字典。

堆棧跟蹤:

在System.Collections.Generic.Dictionary 2.get_Item(TKey key) at ObservableDictionary.MyObservableDictionary 2.set_Item(TKEY的關鍵,TValue值)在C:\用戶\月\文檔\ Visual Studio 2010的\項目\ PokecMessanger - 好的版本 - 複製\ ObservableDictionary \ MyObservableDictionary.cs:第163行 位於d:\ Development \ Releases \ Json中的Newtonsoft.Json.Utilities.DictionaryWrapper`2.System.Collections.IDictionary.set_Item(Object key,Object value) \ Working \ Src \ Newtonsoft.Json \ Utilities \ DictionaryWrapper.cs:line 353

可觀察字典類:

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 
} 

JSON字符串是這樣的:

{ 
    "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 ... 
} 

問題代碼:

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

友元類是這樣的:

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

請提前,我不知道什麼是錯的。謝謝。在反序列化中,我使用JSON.NET。

TO喬恩斯基特: 我試試這個

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

回答

2

問題不是JSON - 它是你的字典。看看這段代碼:

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

你如何期望永遠能夠在字典中設置一個值?如果給定密鑰不在字典中,「get」索引器將引發異常。

您需要改爲使用TryGetValue,並且只有在密鑰實際存在於第一位時才檢查相等性。

值得注意的是,在您嘗試在JSON反序列化的上下文中使用它之前,您應該已經能夠通過單元測試您的字典類型來找到此問題。

編輯:異常發生在設置器,因爲你總是試圖訪問底層字典的getter。你需要它是這樣的:

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

我試過但它不起作用,你能給我一個代碼示例嗎?謝謝 – Joe 2010-11-07 12:01:31

+0

@Joe:是的,它*做*工作。請顯示您嘗試過的內容 - 嘗試更改字典設置器來編輯您的問題。 – 2010-11-07 12:19:32

+0

是的先生Skeet我編輯了我的主題。 – Joe 2010-11-07 12:34:59