序列化&反序列化包含类键

时间:2017-03-08 17:15:23

标签: c# json dictionary serialization deserialization

我试图序列化我的字典:

private Dictionary<MetaDataKey, User> _dictionary;

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

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类中获取了Users的字段。 即使在我解决它之后,我仍然会遇到异常:

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

当我尝试加载非空文件时。 总之,有两个问题: 1.糟糕的json储蓄。 2.糟糕的json加载

2 个答案:

答案 0 :(得分: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; }
}

答案 1 :(得分:0)

来自Json.Net的文档:

  

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

您有两种选择:

  1. 就像文档建议的那样:为TypeConverter创建MetaDataKey并将其与属性([TypeConverter(typeof(MetaDataKeyConverter))])相关联 - 这不是一件容易的事,因为您必须转换MetaDataKey你自己的json字符串,也可以从字符串反序列化。
  2. 为字典创建JsonConverter并在JsonConvert.SerializeObjectJsonConvert.DeserializeObject方法中使用它。
  3. 您可以做的最简单的事情是将dictinary转换为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);
    
  4. 对于大多数情况,我会选择选项3