使用 JSON.NET 将 JSON 反序列化为可观察字典 [C#]
我尝试将 JSON 字符串反序列化为可观察字典。如果我使用 .NET 中的普通通用字典,效果很好,但如果我尝试使用我自己的可观察字典,则会出现异常:
字典中不存在给定的键。
StackTrace:
at System.Collections.Generic.Dictionary
2.get_Item(TKey key) 在 ObservableDictionary.MyObservableDictionary
2.set_Item(TKey key, TValue value) 在 C:\Users\Jan\Documents\Visual Studio 2010\Projects\PokecMessanger-好版本 - Copy\ObservableDictionary\MyObservableDictionary.cs:line 163 在 Newtonsoft.Json.Utilities.DictionaryWrapper`2.System.Collections.IDictionary.set_Item(对象键,对象值) 在 d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Utilities\DictionaryWrapper.cs:line 353
Observable 字典类:
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());
Friend 类如下所示:
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。
致乔恩·斯基特: 我试试这个
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"));
}
}
}
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)
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 ObservableDictionary.MyObservableDictionary
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"));
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题不在于 JSON,而在于你的字典。看看这段代码:
你期望如何在字典中设置一个值?如果给定的键不在字典中,“get”索引器将抛出异常。
您需要使用
TryGetValue
代替,并且仅当密钥实际上首先存在时才检查相等性。值得注意的是,在尝试在 JSON 反序列化上下文中使用字典类型之前,您应该能够通过对字典类型进行单元测试来发现这个问题。
编辑:异常发生在 setter 中,因为您总是尝试访问底层字典的 getter。你需要它是这样的:
The problem isn't JSON - it's your dictionary. Look at this code:
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: