Im trying to serialize my dictionary that looks like that:
private Dictionary<MetaDataKey, User> _dictionary;
where MetaDataKey and Users classes looks like that:
internal class User
{
public string UserName { get; set; }
public string UserPassword { get; set; }
public List<Account> Accounts { get; set; }
}
internal class Account
{
public string Subject { get; set; }
public string AccName { get; set; }
public string AccPass { get; set; }
public List<string> Notes { get; set; }
}
internal class MetaDataKey
{
public string Name { get; set; }
public string Password { get; set; }
}
I am trying to save\load the dictionary to\from a json file like this:
private void DictionaryInit()
{
//gets the dictionary file if exists, create an empty one if not.
string path = Directory.GetCurrentDirectory() + "\\dic.json";
if (!File.Exists(path))
{
_dictionary = new Dictionary<MetaDataKey, User>();
return;
}
using (StreamReader r = new StreamReader(path))
{
string json = r.ReadToEnd();
_dictionary = JsonConvert.DeserializeObject<Dictionary<MetaDataKey, User>>(json);
}
}
public void DictionarySave()
{
//save the dictionary into dic.json file
string path = Directory.GetCurrentDirectory() + "\\dic.json";
string json = JsonConvert.SerializeObject(_dictionary);
File.WriteAllText(path, json);
}
when I am loading a new record to the dictionary and trying to save it I get:
{"WpfApplication2.MetaDataKey":{"UserName":"Enter Name","UserPassword":"Enter Password","Accounts":null}}
instead of:
{"WpfApplication2.MetaDataKey":{"Name":"Enter Name","Password":"Enter Password"},"WpfApplication2.User":{"UserName":"Enter Name","UserPassword":"Enter Password","Accounts":null}}
as you can tell, I am getting the fields of Users in MetaDataKey class. even after I fix it manualy I am still getting exception:
An exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in Newtonsoft.Json.dll but was not handled in user code
when I am trying to load a non-empty file. In conclusion, 2 problems: 1. bad json saving. 2. bad json loading
From the documentation of Json.Net:
When serializing a dictionary, the keys of the dictionary are converted to strings and used as the JSON object property names. The string written for a key can be customized by either overriding ToString() for the key type or by implementing a TypeConverter. A TypeConverter will also support converting a custom string back again when deserializing a dictionary.
You have two options:
TypeConverter for your MetaDataKey and link it with attribute ([TypeConverter(typeof(MetaDataKeyConverter))]) - This is not trivial as you will have to convert the MetaDataKey to json string yourself, and also deserialize from string.JsonConverter for dictionary and use it in your JsonConvert.SerializeObject and JsonConvert.DeserializeObject methods.The simplest thing you can do is to convert the dictinary to a List<KeyValuePair<MetaData,User>> this is easy as _dictionary.ToList()
So for serializing:
string json = JsonConvert.SerializeObject(_dictionary.ToList());
And for deserialize:
_dictionary =
JsonConvert.DeserializeObject<List<KeyValuePair<MetaDataKey, User>>>(json)
.ToDictionary(kv => kv.Key, kv => kv.Value);
For most cases I would choose option 3
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With