2017-03-08 49 views
2

我试着去序列化我的字典里,看起来像一本字典:序列化和反序列化包含类关键字

private Dictionary<MetaDataKey, User> _dictionary; 

其中MetaDataKey和用户类看起来像这样:

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

我想从这样的json文件保存\加载字典到\:

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

我在装载一个新的记录到字典,并试图挽救它,我得到:

{"WpfApplication2.MetaDataKey":{"UserName":"Enter Name","UserPassword":"Enter Password","Accounts":null}} 

代替:

{"WpfApplication2.MetaDataKey":{"Name":"Enter Name","Password":"Enter Password"},"WpfApplication2.User":{"UserName":"Enter Name","UserPassword":"Enter Password","Accounts":null}} 

,你可以告诉我得到在MetaDataKey类用户的领域。 即使我修复它manualy我仍然得到异常:

An exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in Newtonsoft.Json.dll but was not handled in user code 

当我试图加载非空文件。 总之,2个问题: 1.糟糕的json节约。 2.坏JSON装载

+0

我们可以看到一个json文件包含的例子吗? – maccettura

+0

第一次是空的,我添加一个记录后,我得到这个文件:{“WpfApplication2.MetaDataKey”:{“UserName”:“Enter Name”,“UserPassword”:“Enter Password”,“Accounts”: null}} (与iive发布相同) –

+0

它看起来像Newtonsoft JSON序列化程序使用键对象的ToString表示形式作为键。默认的ToString表示是完整的类名(= namespace.classname)。 – ckuri

回答

0

尝试使用JsonProperty属性类似如下:

internal class User 
{ 

[JsonProperty("UserName ")] 
public string UserName { get; set; } 

[JsonProperty("UserPassword")] 
public string UserPassword { get; set; } 

[JsonProperty("Accounts ")] 
public List<Account> Accounts { get; set; } 
} 
+0

我得到了同样的结果。 –

+0

请参阅本[指南](http://www.newtonsoft.com/json/help/html/SerializationGuide.htm) –

0

Json.Net文档:

当序列化的字典,所述字典的键被转换字符串并用作JSON对象属性名称。为关键字编写的字符串可以通过覆盖键类型的ToString()或通过实现TypeConverter来定制。在反序列化字典时,TypeConverter还支持再次转换自定义字符串。

你有两个选择:

  1. 如文档建议:为您创造MetaDataKey一个TypeConverter与属性([TypeConverter(typeof(MetaDataKeyConverter))])将其链接 - 这是不平凡的,你必须将MetaDataKey转换为json字符串自己,并从字符串反序列化。
  2. 为字典创建JsonConverter并在JsonConvert.SerializeObjectJsonConvert.DeserializeObject方法中使用它。
  3. 最简单的件事你可以做的是词典]转换为List<KeyValuePair<MetaData,User>>这是很容易为_dictionary.ToList()
    所以序列化:

    string json = JsonConvert.SerializeObject(_dictionary.ToList()); 
    

    而对于反序列化:

    _dictionary = 
          JsonConvert.DeserializeObject<List<KeyValuePair<MetaDataKey, User>>>(json) 
          .ToDictionary(kv => kv.Key, kv => kv.Value); 
    

对于大多数情况下,我会选择选项3