我尝试将JSON字符串反序列化为可观察字典。如果我使用.NET中的普通通用字典,它可以正常工作,但如果我尝试使用自己的可观察字典,我会得到例外:
字典中没有给定的密钥。
堆栈跟踪:
at System.Collections.Generic.Dictionary
2.get_Item(TKey key) at ObservableDictionary.MyObservableDictionary
2.set_Item(TKey key,TValue value)在C:\ Users \ Jan \ Documents \ Visual Studio 2010 \ Projects \ PokecMessanger-good version - Copy \ ObservableDictionary \ MyObservableDictionary.cs:第163行 at Newtonoft.Json.Utilities.DictionaryWrapper`2.System.Collections.IDictionary.set_Item(Object key,Object value)in d:\ Development \ Releases \ Json \ 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 JON SKEET: 我试试这个
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"));
}
}
}
答案 0 :(得分:2)
问题不是JSON - 这是你的字典。看看这段代码:
public TValue this[TKey key]
{
get { return _dictionary[key]; }
set
{
bool changed = _dictionary[key].Equals(value);
...
}
}
您如何期望能够在字典中设置值?如果给定的键不在字典中,“get”索引器将抛出异常。
您需要使用TryGetValue
,而只检查密钥是否实际存在于第一位。
值得注意的是,在尝试在JSON反序列化的上下文中使用它之前,您应该能够通过单元测试字典类型来找到此问题。
编辑: setter 中发生异常,因为您总是试图访问基础字典的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.
}