-1

Using the below code, I'm trying to save app settings data in JSON format so it's easily readable and (in theory) easy to load back directly into data structures. Unfortunately it's not working out that way.

My general strategy is to ahve a series of lists representing different types of settings which I'll drop into one ListDictionary and then save as a single JSON object. Then, in theory, I load it back to a ListDictionary and recast the values into the lists they started as.

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

Instead, I'm getting the error in the title on the quickPaths assignment in the Prefs() constructor. I've looked it up and there's nothing else out there about this error specifically and no workarounds I've been able to find.

I've tried iterating over the prefs["quickPaths"] value and manually adding them one at a time to the List, but that's both inelegant and doesn't work anyway. Clearly I'm doing something wrong, but I don't know what. I thought I would get from deserialize exactly what I serialized, but it seems it doesn't work that way.

Here's what the output of the save function looks like:

{"quickPaths":["C:\\output","C:\\Users","C:\\Windows"]}
not_a_generic_user
  • 1,906
  • 2
  • 19
  • 34
  • 3
    is it possible to see how `ListDictionary` defined and how the json looked like? `JsonElement` is pretty generic it can be number, dates, object, and even array.. fyi, [using dynamic might help](https://stackoverflow.com/a/47896393). – Bagus Tesa May 06 '22 at 14:27
  • I added the output of the save command above. – not_a_generic_user May 06 '22 at 20:06
  • I tried converting my project to using the Newtonsoft.json that you recommended in your link, but it had the same result. Same error on the same line. Not sure what you mean by seeing how "ListDictionary is defined". All the code using it is present above. – not_a_generic_user May 06 '22 at 20:12
  • my bad, i didnt realized `ListDictionary` was in .Net. people usually will just use `Dictionart` and its known both `System.Text.Json` and `Newtonsoft.Json` supports it. also, i'm not telling you to change over to newtonsoft. i'm asking you to try the `Dictionary`. – Bagus Tesa May 06 '22 at 22:28

2 Answers2

0

Try with the Newtonsoft like this

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

}

or you can deserialize one more time, like

quickPaths = JsonSerializer.Deserialize<List<string>>(((JsonElement)prefs["quickPaths"]).GetRawText()); 
  • and also why are you deserialize into ListDictionary? – r.lakusta May 06 '22 at 20:38
  • I don't recall why I thought ListDictionary was the way to go, but it appears that it was the wrong choice. I managed to resolve it with the build-in JSON stuff by changing around a few things including not using ListDictionary. – not_a_generic_user May 06 '22 at 20:56
0

I tried the Newtonsoft method including the deserializing of the sub-element and it didn't work (at least not how I implemented it).

Instead I re-evaluated my data structures and got rid of the ListDictionary in favor of Dictionary<string,List> since that's what I was doing anyway.

From there, I just needed to convert the comma-separated string to a list which can be done with built-in functions like so:


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

not_a_generic_user
  • 1,906
  • 2
  • 19
  • 34