Reputation: 91
I try deserialize JSON string to observable dictionary. If I use normal generic dictionary from .NET it works good, but if I try use my own observable dictionary i get exception:
The given key was not present in the dictionary.
StackTrace:
at System.Collections.Generic.Dictionary
2.get_Item(TKey key) at ObservableDictionary.MyObservableDictionary
2.set_Item(TKey key, TValue value) in C:\Users\Jan\Documents\Visual Studio 2010\Projects\PokecMessanger-good version - Copy\ObservableDictionary\MyObservableDictionary.cs:line 163 at Newtonsoft.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
Observable dictionary class:
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 string look like this :
{
"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 ...
}
Problem code:
MyObservableDictionary<string, FriendData> friends = new MyObservableDictionary<string, FriendData>();
//problem is here
friends = JsonConvert.DeserializeObject<MyObservableDictionary<string, FriendData>>(jsonString.ToString());
Friend class look like this:
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;
}
}
Please, any advance, I don’t know what can be wrong. Thank you. On deserialization I use JSON.NET.
TO JON SKEET: i try this
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"));
}
}
}
Upvotes: 0
Views: 2456
Reputation: 1500835
The problem isn't JSON - it's your dictionary. Look at this code:
public TValue this[TKey key]
{
get { return _dictionary[key]; }
set
{
bool changed = _dictionary[key].Equals(value);
...
}
}
How do you expect to ever be able to set a value in the dictionary? The "get" indexer will throw an exception if the given key isn't in the dictionary.
You need to use TryGetValue
instead, and only check for equality if the key was actually present in the first place.
It's worth noting that you should have been able to find this problem by unit testing your dictionary type before you ever got as far as trying to use it in the context of JSON deserialization.
EDIT: The exception is occurring in the setter because you're always trying to access the underlying dictionary's getter. You need it to be something like this:
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.
}
Upvotes: 2