WinUI3- read and write .json files

Original link

WinUI3-Reading and writing .json files – WhiteNight's Site

May 24, 2023

However, I'm new to Javascript myself. Here is just sharing one of them, a method that is feasible after my own testing.

Application Scenario

When to use .json

Take the problem I encountered when writing a Redis visualization tool as an example.

The user opens the application and sets the IP and password of the Redis server on the setting interface. However, it is impossible for the application to hang in the background all the time, and it will be closed by the user sooner or later.

Then the question is, when the user opens the application again, will the IP and password set last time be automatically saved? Of course not, the program loads your preset code. If you preset the IP in the program as "127.0.0.1", then no matter how many times the user restarts the application, the default IP is still "127.0.0.1".

Of course, it's fine to let the user set it up every time they launch the app. But for a good user experience, I was thinking "how can I save the data entered by the user last time locally"?

write to txt? and then read each time? It is very convenient to write, but very troublesome to read. Every time you read txt, you have to match and split the string. It is really troublesome to implement the code.

Just recently, I was studying how to crawl the schedule of the "Shenzhen University of Technology Educational Administration System", and I came into contact with Javascript and .json format for the first time. I found that the .json file is too easy to use. C# has its own method for processing the Json format. Originally, I had to write the code for splitting the string. Now people can directly package it for you and use it directly.

a .json file

WinUI3 does not "support" for now

Why do you say pinching is not supported? You open your project, right click and select Add - New Item. Searched for .json and found only configuration json for TypeScript and Javascript.

But it doesn't mean that WinUI3 programs can't read .json, it's just that the winui3 project in vs won't be added for you, that's all.

Go directly to the folder and create a new .json file yourself; or use vs to open the folder where you need to add the .json file (do not select .sln to enter the project), then select Add-New Item, find .json in the web column, and select Add it and you're done.

So what is the format of the .json file? Let me take my InitSetting.json as an example

[
  {
    "databaseIP": "127.0.0.1",
    "databasePassword": null
  }
]

The json file specifies the address and password of the database.

The path where .json is stored

Do not store non-packaged programs in the AppData folder of the C drive

Since you want to read the .json file, you must have its path and its file name, right? I personally recommend storing the .json of user configuration in the same path as your program. For example, create a new folder AppData, and then throw .json into it.

Personally, it is recommended not to save (friendly words, which have been automatically blocked) in the AppData folder of the C drive, especially for programs that choose to be packaged (Packaged). Not to mention that because a bunch of applications are throwing things into AppData, I have to clean up this folder for a long time every time.

Another main reason is: choose the unpackaged (Unpackaged) program to run, it is impossible to pass

private static string ApplicationData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);

and a series of methods to obtain the environment folder of the application (that is, the AppData directory of the C drive). This is why when you choose to run the program without packaging, you will report an error using these methods. Because the application does not know which folder this method points to when it is not packaged.

read.json

Read the file first, then divide the string

Taking SimpleString as an example, it is recommended to refer to the code of the warehouse before looking at the following content.

There is an AppData folder under the application directory, and there is an InitSetting.json file in this folder. This file holds the data that I want to persist after the application is closed - the database address and the database password.

Then the code to open InitSetting.json is as follows

  private async void InitDatabase()
        {
            string fileName = "AppData/InitSettings.json";
            string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,fileName);

            string databaseIP = null;
            string databasePassword = null;
            if (File.Exists(filePath))
            {
             string json = await File.ReadAllTextAsync(filePath);
            }

        }

This code is not difficult to understand, it is simply an operation to open the json file and write all the contents in the file into a string.

Next is to split the string. First look at the content of the json file

[
  {
    "databaseIP": "127.0.0.1",
    "databasePassword": null
  }
]

For json, square brackets "[ ]" are equivalent to a start tag, curly brackets "{ }" are equivalent to an array, and inside the curly brackets are its objects - that is, it can be simply understood as a C++ object array .

Then we will use "JsonArray" next. Divide the string into an array of Json type. Then traverse the array to determine the corresponding value. code show as below

tring json = await File.ReadAllTextAsync(filePath);
                JsonArray data = (JsonArray)JsonArray.Parse(json);
                foreach (var item in data)
                {
                    if(item["databaseIP"] != null)
                        databaseIP = item["databaseIP"].ToString();
                    if (item["databasePassword"] != null)
                        databasePassword = item["databasePassword"].ToString();
                }

                Settings.databaseInfo.databaseIP = databaseIP;
                Settings.databaseInfo.databasePassword = databasePassword;

The above method is suitable for the case of "looking for a specific key name".

There is another method, which is suitable for the case of "don't need to consider the key name". This method is what I tried in "Write the key-value pairs in the json file to Redis". This method will also be more intuitive to use.

Of course, this code is a bit long, and I didn't write a comment. It is recommended to copy it to vs. code show as below

    private async void JsonToRedis(object sender, RoutedEventArgs e)
        {
            string fileName = "AppData/RedisKey.json";
            string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
           try
           { 
                configurationOptions = new ConfigurationOptions
                {
                    EndPoints = { $"{Settings.databaseInfo.databaseIP}" },
                    Password = $"{Settings.databaseInfo.databasePassword}"
                };
                connectionMultiplexer = ConnectionMultiplexer.Connect(configurationOptions);
                database = connectionMultiplexer.GetDatabase();
            }
            catch
            {
                ErrorMessage_CantFindRedis();
            }

            try
            {
                string keyName = null;
                string keyValue = null;
                long TTL = (long)TTLSetter.Value;
                if (File.Exists(filePath))
                {
                    string json = await File.ReadAllTextAsync(filePath);
                    JsonArray data = (JsonArray)JsonArray.Parse(json);
                    TimeSpan timeSpan;
                    if (TTLType == "s")
                    {
                        timeSpan = TimeSpan.FromSeconds((long)TTLSetter.Value);
                    }
                    else if (TTLType == "ms")
                    {
                        timeSpan = TimeSpan.FromMilliseconds((long)TTLSetter.Value);
                    }
                    else
                    {
                        timeSpan = TimeSpan.Zero;
                    }
                    foreach (var item in data)
                    {
                        var props = item.AsObject();
                        foreach (var prop in props)
                        {
                            keyName = prop.Key;
                            keyValue = prop.Value.ToString();
                            if (TTL != 0)
                            {
                                database.StringSet(keyName, keyValue, timeSpan);
                            }
                            else
                            {
                                database.StringSet(keyName, keyValue);
                            }
                        }

                    }
                }
            }
            catch
            {
                ErrorMessage_UnsupportedMethod();
            }
        }

Roughly explain a few points:

  • try-catch is used to catch exceptions. Prevent the app from crashing directly when encountering an exception. The code that triggers the pop-up window can be added to the catch part to indicate that the program is running abnormally.
  • The Timespan class is used to handle time. The main reason is that the key-value pairs in Redis have the operation of setting TTL (Time to live). I want the user to see "Choose to set a TTL of 61 seconds, and the TTL displayed to the user on the front end is set to a TTL of one minute and one second". So it will be much more convenient to use Timespan.
  • Unlike the first method, the second method does not need to consider the specific meaning of the key name and key value. So there is another loop inside the foreach. To get the key name and key value of each object in JsonArray.

Writer's note

This part really recommends writing it yourself. The meaning and content of different program json files are also likely to be different. If you can't understand it, you can try to change it according to the code on Github, and set a few more breakpoints to debug and debug.

Delete other irrelevant codes, if the core code is released directly, as follows

string keyName = null;
                string keyValue = null;
                if (File.Exists(filePath))
                {
                    string json = await File.ReadAllTextAsync(filePath);
                    JsonArray data = (JsonArray)JsonArray.Parse(json);
                  
                    foreach (var item in data)
                    {
                        var props = item.AsObject();
                        foreach (var prop in props)
                        {
                            keyName = prop.Key;
                            keyValue = prop.Value.ToString();
                            }
                        }

                    }
                }

write json file

reverse operation of read

To put it bluntly, writing is the reverse operation of reading. The same is "convert to Json object, write the whole document at once".

First is serialization. First make sure what your key name and key value are. Still taking SimpleString as an example, I need to save the database address and password. Then the key name is the database address, and the key value is the database password. Then create a new object to represent the key-value pair.

   public class DatabaseInfo
        {
            public string databaseIP { get; set; }
            public string databasePassword { get; set; }
        }

The next step is to serialize the object.

   private void SaveIPAndPassword(object sender, RoutedEventArgs e)
        {
            string fileName = "AppData/InitSettings.json";
            string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
            
            try
            {
                List<DatabaseInfo>_data=new List<DatabaseInfo>();
                _data.Add(new DatabaseInfo()
                {
                    databaseIP = databaseInfo.databaseIP,
                    databasePassword = databaseInfo.databasePassword
                });
                string json = JsonSerializer.Serialize(_data);
                File.WriteAllText(filePath, json);
            }catch
            {
                ErrorMessage_CantSaveIPAndAddress();
            }
        }

In fact, the most important thing is this line of code. This line of code means to serialize the _data object into a string.

 string json = JsonSerializer.Serialize(_data);

Of course, this is just a code example. How to change the specific details depends on what data your program needs to save locally and what type of data needs to be read, but the general idea is the same.

Guess you like

Origin blog.csdn.net/white_night_SZTU/article/details/130861234