无法通过 JSON - 'System.Text.Json.JsonElement' 保存然后加载应用程序设置以键入 'System.Collections.Generic.List`1[System.String]'。'

Unable to save and then load app settings via JSON - 'System.Text.Json.JsonElement' to type 'System.Collections.Generic.List`1[System.String]'.'

使用下面的代码,我试图以 JSON 格式保存应用程序设置数据,以便它易于阅读并且(理论上)易于直接加载回数据结构。不幸的是,事情并非如此。

我的一般策略是创建一系列代表不同类型设置的列表,我将它们放入一个 ListDictionary,然后另存为单个 JSON object。然后,理论上,我将它加载回 ListDictionary 并将值重新转换为它们开始的列表。

        // Paths to pin to quick menu in Windows Explorer
        public List<string> quickPaths = new List<string>();

        public string diag = "";
        public string settingsFile = System.AppDomain.CurrentDomain.BaseDirectory + "customizer_settings.json";


        public Prefs()
        {
            ListDictionary prefs = LoadPrefs();
            quickPaths = (List<string>)prefs["quickPaths"];
        }


        public ListDictionary LoadPrefs() 
        { 
            if (!File.Exists(settingsFile)) return new ListDictionary();
            string json = File.ReadAllText(settingsFile);
            return JsonSerializer.Deserialize<ListDictionary>(json);
        }

        public void SavePrefs()
        {
            ListDictionary toSave = new ListDictionary();
            toSave["quickPaths"] = quickPaths;
            File.WriteAllText(settingsFile, JsonSerializer.Serialize(toSave));
        }

相反,我在 Prefs() 构造函数中的 quickPaths 分配的标题中收到错误。我已经查过了,没有其他关于这个错误的具体信息,也没有我能找到的解决方法。

我试过遍历 prefs["quickPaths"] 值并手动将它们一次一个地添加到列表中,但这既不优雅又不起作用。显然我做错了什么,但我不知道是什么。我以为我会从反序列化中得到我序列化的东西,但它似乎不是那样工作的。

保存函数的输出如下所示:

{"quickPaths":["C:\output","C:\Users","C:\Windows"]}

像这样使用 Newtonsoft 试试

public class Prefs
{
    public List<string> quickPaths = new List<string>();

    public string diag = "";
    public string settingsFile = System.AppDomain.CurrentDomain.BaseDirectory + "customizer_settings.json";


    public Prefs()
    {
        ListDictionary prefs = LoadPrefs();
        quickPaths =  ((JArray)prefs["quickPaths"]).ToObject<List<string>>();
      
    }


    public ListDictionary LoadPrefs()
    {
        if (!File.Exists(settingsFile)) return new ListDictionary();
        string json = File.ReadAllText(settingsFile);
        return JsonConvert.DeserializeObject<ListDictionary>(json);
    }

    public void SavePrefs()
    {
        ListDictionary toSave = new ListDictionary();
        toSave["quickPaths"] = quickPaths;
        File.WriteAllText(settingsFile, JsonConvert.SerializeObject(toSave));
    }

}

或者你可以再反序列化一次,比如

quickPaths = JsonSerializer.Deserialize<List<string>>(((JsonElement)prefs["quickPaths"]).GetRawText()); 

我尝试了 Newtonsoft 方法,包括 sub-element 的反序列化,但它没有用(至少不是我的实现方式)。

相反,我 re-evaluated 我的数据结构并摆脱了 ListDictionary,转而使用 Dictionary,因为无论如何我就是这样做的。

从那里开始,我只需要将 comma-separated 字符串转换为列表,这可以通过 built-in 函数完成,如下所示:


        // Paths to pin to quick menu in Windows Explorer
        public List<string> quickPaths = new List<string>();

        public string diag = "";
        public string settingsFile = System.AppDomain.CurrentDomain.BaseDirectory + "customizer_settings.json";


        public Prefs()
        {
            Dictionary<string,List<string>> prefs;
            prefs = LoadPrefs();
            quickPaths = prefs["quickPaths"].ToList<string>();
        }


        public Dictionary<string,List<string>> LoadPrefs() 
        { 
            if (!File.Exists(settingsFile)) return new Dictionary<string,List<string>>();
            string json = File.ReadAllText(settingsFile);
            return JsonSerializer.Deserialize<Dictionary<string,List<string>>>(json);
        }

        public void SavePrefs()
        {
            Dictionary<string,List<string>> toSave = new Dictionary<string,List<string>>();
            toSave["quickPaths"] = quickPaths;
            File.WriteAllText(settingsFile, JsonSerializer.Serialize(toSave));
        }