Click here to Skip to main content
15,867,686 members
Articles / Programming Languages / C#
Tip/Trick

Save Your Settings in a File in JSON and using LINQ for Read and Save

Rate me:
Please Sign up or sign in to vote.
4.83/5 (15 votes)
25 Sep 2023CPOL1 min read 24.4K   30   18
Save Key and Value in JSONformat using C# and LINQ
If you often find yourself creating standalone projects that need to save Global app information for example form settings, maybe this article will be helpful. I often find myself reinventing the wheel, instead of using this class for reading writing and updating a key - value.

Introduction

Saving to a Key-Value file is a simple and useful operation for any type of software, although, from my experience, you can easily run into agility problems when retrieving this information.

Using this class and with little effort, you can view, create, modify a key. Using LINQ (one of the wonders of the world), you can search for a specific key or display all of them.

A boon for anyone beginning to write code.

Background

You can add this simple class into your project and immediately start saving the information to a Json format file disguising it with any extension.

Once you've inserted this class, you'll need to include the Newtonsoft.Json nuget library with a simple CTRL+.
Then, using Linq and with very little effort, you can read all the information one by one or all at once.

Using the Code

So let's start: in our project, we insert a new class:

C#
using Newtonsoft.Json;
using System.Collections.Generic;
using System.IO;
using System.Linq;
 
namespace SettingsFileClass
{
    public class SettingsInJsonFile
      {
          // Here, you have to set the network path where you want to insert the file
          // For example, you can use c:\MyTestApp\Settings.ini
          //                         c:\program files\MyTestApplication\MainConfig.config
          // Or you can use Isolated storage for location your file
          public const string FilePath = @"D:\temp\settings.json";
          // You can choose if you prefer indented or none (more space saving)
          public const Formatting MyFormatting = Formatting.Indented;
 
          /// <summary>
          /// Class Settings
          /// </summary>
          internal string _key;
          public string Key { get { return _key; } set { _key = value.ToUpper(); } }
          public string? Value { get; set; }
 
          /// <summary>
          /// Set a new value in a Key if exists. You can use for create a new key using
          /// Optional value (by default, return false if Key not exist
          /// </summary>
          /// <param name="Key">This string will be saved only uppercase</param>
          /// <param name="NewValue">New value in string type</param>
          /// <param name="CreateIfNew">bool true = create, false = not create</param>
          /// <returns></returns>
          internal static bool Set(string Key, string NewValue, bool CreateIfNew = false)
          {
              Key = Key.ToUpper();
              var Item = GetObject(Key);
              var _data = GetAll().ToList();
 
              if (Item == null)
              {
                  //Not found -> user choice if create
                  if (CreateIfNew)
                  {
                      //Add new key in Data Items
                      _data.Add(new SettingsInJsonFile()
                      {
                          Key = Key,
                          Value = NewValue
                      });
                  }
                  else
                  {
                      //Not found, not allow to create
                      return false;
                  }
              }
              else
                  _data.First(x => x.Key == Key).Value = NewValue; //Update value
 
              string json = JsonConvert.SerializeObject(_data.ToArray(), MyFormatting);
              //write string to destination
              File.WriteAllText(FilePath, json);
 
              return true;
          }
          internal static bool Delete(string KeyToDelete)
          {
              if (Exist(KeyToDelete))
              {
                  var _data = GetAll().Where
                      (x => x.Key != KeyToDelete.ToUpper()).ToArray();
                  string json = JsonConvert.SerializeObject(_data, MyFormatting);
 
                  //write string to destination
                  File.WriteAllText(FilePath, json);
 
                  return true;
              }
              return false;
          }
          internal static List<SettingsInJsonFile> GetAll()
          {
              //Create file Settings if not exists
              if (!File.Exists(FilePath))
              {
                  //Creation of new file with Initialization ->"[]"
                  using StreamWriter wr = File.CreateText(FilePath);
                  wr.WriteLine("[]");
              }
 
              using StreamReader r = new(FilePath);
              string json = r.ReadToEnd();
              if (string.IsNullOrEmpty(json)) json = "[]";
              var Response = JsonConvert.DeserializeObject
                             <List<SettingsInJsonFile>>(json);
              return Response;
          }
 
          internal static string GetValue(string Key) => 
                   GetAll().FirstOrDefault(x => x.Key == Key.ToUpper()).Value;
          internal static SettingsInJsonFile? GetObject(string Key) => 
                   GetAll().FirstOrDefault(x => x.Key == Key.ToUpper());
          internal static bool Exist(string Key) => GetAll().FirstOrDefault
                   (x => x.Key == Key.ToUpper()) != null;
 
      }
}

The file result in the file is, for example:

JavaScript
[
    {"Key":"key","Value":"07/10/2022 13:04:21"},
    {"Key":"backcolor","Value":"#FFFFFF"}
    {"Key":"forecolor","Value":"#000000"}
]

Points of Interest

This simple class is powerful enough for small text files used for local storage. I would not recommend it for more complex scenarios or where the number of variables begin to grow exponentially.

The function "CREATE" create Keys, but these keys are Keysensitive, so a good check to add would be to create all keys as uppercase only.

History

  • 7th October, 2022: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Italy Italy
Over 20-years experience in using Microsoft technologies.
At present, I work as a Senior Developer and IT manager at a metalworking company, I also offer consultancy as a high level freelance on cloud technologies and software development.

Comments and Discussions

 
SuggestionUse ConfigurationBinder.Bind Method Pin
dievdo26-Sep-23 23:19
professionaldievdo26-Sep-23 23:19 
SuggestionOr keep it simple Pin
MSBassSinger26-Sep-23 11:55
professionalMSBassSinger26-Sep-23 11:55 
SuggestionRe: Or keep it simple Pin
dievdo27-Sep-23 0:53
professionaldievdo27-Sep-23 0:53 
QuestionUse a SQLite database Pin
chris.locke26-Sep-23 3:51
chris.locke26-Sep-23 3:51 
QuestionWhy double ToUpper? Pin
Heiko F. Scholze26-Sep-23 1:36
professionalHeiko F. Scholze26-Sep-23 1:36 
QuestionWhy don't you use the builtin appsettings mechanism Pin
Klaus Luedenscheidt25-Sep-23 18:50
Klaus Luedenscheidt25-Sep-23 18:50 
AnswerRe: Why don't you use the builtin appsettings mechanism Pin
chris.locke26-Sep-23 3:49
chris.locke26-Sep-23 3:49 
GeneralRe: Why don't you use the builtin appsettings mechanism Pin
Peter Adam29-Sep-23 23:51
professionalPeter Adam29-Sep-23 23:51 
QuestionHmm... what's this for? Pin
Jeff Bowman17-Oct-22 10:41
professionalJeff Bowman17-Oct-22 10:41 
AnswerRe: Hmm... what's this for? Pin
Dario Picca17-Oct-22 17:54
Dario Picca17-Oct-22 17:54 
QuestionSections and Default values. Pin
Patrick Blackman16-Oct-22 1:47
professionalPatrick Blackman16-Oct-22 1:47 
Can we store the setting in a section e.g. Appearance, Communication etc. also for each value stored, can we also store a default value e.g. : Section = "Buildings", Key = "House Type", Value = "Two Storey", Default = "Bungalow"
AnswerRe: Sections and Default values. Pin
Dario Picca17-Oct-22 16:16
Dario Picca17-Oct-22 16:16 
GeneralRe: Sections and Default values. Pin
Patrick Blackman17-Oct-22 17:08
professionalPatrick Blackman17-Oct-22 17:08 
QuestionAn Alternative Approach Pin
George Swan9-Oct-22 19:43
mveGeorge Swan9-Oct-22 19:43 
AnswerRe: An Alternative Approach Pin
Dario Picca10-Oct-22 22:19
Dario Picca10-Oct-22 22:19 
GeneralRe: An Alternative Approach Pin
cphv11-Oct-22 17:36
cphv11-Oct-22 17:36 
QuestionSome Observations Pin
George Swan8-Oct-22 18:43
mveGeorge Swan8-Oct-22 18:43 
AnswerRe: Some Observations Pin
Dario Picca9-Oct-22 16:52
Dario Picca9-Oct-22 16:52 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.