crud

How to make CRUD operations in a JSON file using C# and Newtonsoft.Json

In this tutorial, I will teach you how to implement CRUD (Create, Read, Update, Delete) functionality on a JSON file using C# and the Newtonsoft.Json library.

JSON (JavaScript Object Notation) is a subset of JavaScript and is a very lightweight data exchange format, which is also one of the reasons why it’ so popular with an API. Often we want to use JSON in a project, where we are able to access data very fast. We would like to be able to skip the part where we create a connection, check availability, the status of endpoint, post data, receive data, etc… we just want a solution, where we don’t depend on another server (for this tutorial).

Imagine an application without a database? In such a scenario, we can store information/data in a JSON file. Therefore we need to be able to perform CRUD operations on JSON files like we are able to do with a database.

Create The Solution in Visual Studio

I will be using Visual Studio 2019 for this tutorial – no database is needed. Below is a brief overview of what we are going to do:

  • Create Console Application with .NET 5.0.
  • Create a JSON file named users.json.
  • Add Dependency (Newtonsoft).
  • Write a Method to get details about Users.
  • Write a Method to add data (append).
  • Write a method to update data.
  • Write a method to delete data.
  • Test it out to see if our functionality behaves as expected.

First, you have to create a new project in Visual Studio. Select the Console Application template and give it the name you want (it doesn’t matter for testing purposes).

Create a new file names users.json in the root of the project and add the following lines of code to the file and save it.

Add User Data in a JSON file

{
  "id": 1,
  "fullname": "John Doe",
  "address": {
    "street": "Jernbanegade 22",
    "city": "Svendborg",
    "zip": 5700
  },
  "jobs": [
    {
      "companyid": 77,
      "companyname": "ISS"
    },
    {
      "companyid": 89,
      "companyname": "DSB"
    },
    {
      "companyid": 22,
      "companyname": "GLS"
    }
  ],
  "phone": 896532417,
  "current-job-role": "Facility Manager"
}

This JSON file contains information about an employee. This includes details like id, name, address, previous jobs, phone, current role, etc… you can add as many details as you want. In the following code, we will be selecting the data on the user, altering it, creating a new previous job, and deleting one again.

Add Newtonsoft Dependency to project

Now right-click on your project and select Manage NuGet Packages... Click on the Browse tab and search for Newtonsoft.json and install the package. You can read more about Newtonsoft.Json here.

Install newtonsoft.json
Install Newtonsoft.Json in Visual Studio Project

When the package has been installed, you can expand the Dependencies tree in the Solution Explorer, to see currently installed packages.

dependencies
Visual Studio Dependencies

Add CRUD methods to project

Create a new file in the root of the project and name it CRUD.cs. This file will contain the CRUD method we will be calling from the main program class to make operations on the users.json file.

Inside this class, some of the JSON actions will take place, so we have to include the using statement of Newtonsoft and we will be performing Linq operations as well. To get access to the newly installed library (Newtonsoft) add the following two lines in the CRUD.cs file.

using Newtonsoft.Json.Linq;
using System.IO;

READ – GetEmployeeDetails()

The first operation we will be performing is reading the data inside the JSON file. We are going to make a method named GetEmployeeDetails(). I will be explaining the code after the block of code below.

public static void GetEmployeeDetails(string jsonFilePath)
        {
            var json = File.ReadAllText(jsonFilePath);
            try
            {
                var jObject = JObject.Parse(json);

                if (jObject != null)
                {
                    Console.WriteLine("ID :" + jObject["id"].ToString());
                    Console.WriteLine("Full Name :" + jObject["fullname"].ToString());

                    var address = jObject["address"];
                    Console.WriteLine("Street :" + address["street"].ToString());
                    Console.WriteLine("City :" + address["city"].ToString());
                    Console.WriteLine("Zip :" + address["zip"]);
                    JArray jobsArray = (JArray)jObject["jobs"];
                    if (jobsArray != null)
                    {
                        foreach (var job in jobsArray)
                        {
                            Console.WriteLine("Job ID :" + job["jobid"]);
                            Console.WriteLine("Company Name :" + job["company"].ToString());
                        }

                    }
                    Console.WriteLine("Phone Number :" + jObject["phone"].ToString());
                    Console.WriteLine("Role :" + jObject["current-job-role"].ToString());

                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Could not read JSON data. More details: ", ex.Message);
                throw;
            }
        }
  • Line 3 – We read the JSON file and access all data points from the specific JSON file from the parameters on the method.
  • Line 6 – Now that the file has been read, we will parse the JSON data using JObject.Parse. This will parse our JSON data and return it as a JObject (Newtonsoft) – it’s actually just an array of data.
  • Rest of code is all about accessesing the data points using the key : value tecnique.

Since data is stored as an array and we would like to access nested data, we have to iterate through the JObject. This is done inside the if statement.

CREATE – AddJob()

In order for us to be able to add new data to an existing JSON file, we need to be sure that we have the data in a structured way, else it can’t be added as new data points to the JSON file. The code below will add a new job to the experience section inside the JSON file.

public static void AddJob(string jsonFilePath)
        {
            Console.WriteLine("Enter Job ID : ");
            var jobId = Console.ReadLine();
            Console.WriteLine("\nEnter Job Name : ");
            var companyName = Console.ReadLine();

            var newJobMember = "{ 'jobid': " + jobId + ", 'company': '" + companyName + "'}";
            try
            {
                var json = File.ReadAllText(jsonFilePath);
                var jsonObj = JObject.Parse(json);
                var jobArrary = jsonObj.GetValue("jobs") as JArray;
                var newJob = JObject.Parse(newJobMember);
                jobArrary.Add(newJob);

                jsonObj["jobs"] = jobArrary;
                string newJsonResult = Newtonsoft.Json.JsonConvert.SerializeObject(jsonObj,
                                       Newtonsoft.Json.Formatting.Indented);
                File.WriteAllText(jsonFilePath, newJsonResult);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Add Error : " + ex.Message.ToString());
            }
        }

What is happening here? The first thing we do is creating a JSON format, with our experience data. Then we add a new job member to the JObject array (JArray).

UPDATE – UpdateJob()

The update operation is a little different from the READ and CREATE operations. When updating, we need to be sure we are interacting with the correct data, that should be updated. In the code below we are selecting a specific Job by ID and then updating the name associated with the job id.

public static void UpdateJob(string jsonFilePath)
        {
            string json = File.ReadAllText(jsonFilePath);

            try
            {
                var jObject = JObject.Parse(json);
                JArray jobsArrary = (JArray)jObject["jobs"];
                Console.Write("Enter Job ID to Update Job : ");
                var jobId = Convert.ToInt32(Console.ReadLine());

                if (jobId > 0)
                {
                    Console.Write("Enter new company name : ");
                    var companyName = Convert.ToString(Console.ReadLine());

                    foreach (var company in jobsArrary.Where(obj => obj["jobid"].Value<int>() == jobId))
                    {
                        company["company"] = !string.IsNullOrEmpty(companyName) ? companyName : "";
                    }

                    jObject["jobs"] = jobsArrary;
                    string output = Newtonsoft.Json.JsonConvert.SerializeObject(jObject, Newtonsoft.Json.Formatting.Indented);
                    File.WriteAllText(jsonFilePath, output);
                }
                else
                {
                    Console.Write("Invalid Job ID, Try Again!");
                    UpdateJob(jsonFilePath);
                }
            }
            catch (Exception ex)
            {

                Console.WriteLine("Update Error : " + ex.Message.ToString());
            }
        }

DELETE – DeleteJob()

The delete operation is easier than the other methods as we can just use the remove method.

public static void DeleteJob(string jsonFilePath)
        {
            var json = File.ReadAllText(jsonFilePath);
            try
            {
                var jObject = JObject.Parse(json);
                JArray jobsArrary = (JArray)jObject["jobs"];
                Console.Write("Enter Job ID to delete Job : ");
                var jobId = Convert.ToInt32(Console.ReadLine());

                if (jobId > 0)
                {
                    var jobName = string.Empty;
                    var jobToBeDeleted = jobsArrary.FirstOrDefault(obj => obj["jobid"].Value<int>() == jobId);

                    jobsArrary.Remove(jobToBeDeleted);

                    string output = Newtonsoft.Json.JsonConvert.SerializeObject(jObject, Newtonsoft.Json.Formatting.Indented);
                    File.WriteAllText(jsonFilePath, output);
                }
                else
                {
                    Console.Write("Invalid Job ID, Try Again.");
                    UpdateJob(jsonFilePath);
                }
            }
            catch (Exception)
            {

                throw;
            }
        }

Again we have to specify what job experience we would like to remove and then we use the .Remove() method on the JArray. If the Job ID is not found, we return an error to the user inside the console.

Add Main functionality inside Program.cs

So now that we got the CRUD actions in place, let’s add a switch to our main method. The switch will be responsible for calling the right method based on input from the user. The code won’t be using a while true solution, where the loop of selecting cases would be indefinite until a certain circumstance. It is just for testing, so the loop will end when the input has been selected.

Below is the code for your main method inside program.cs.

private static readonly string jsonDocument = @"C:\Users\chs\source\repos\JsonCRUDTutorial\JsonCRUDTutorial\users.json";
static void Main(string[] args)
{
    Console.WriteLine("What would you like to do? : 1 - Add Job, 2 - Update Job, 3 - Delete Job, 4 - Select \n");
    var option = Console.ReadLine();
    switch (option)
    {
        case "1":
            CRUD.AddJob(jsonDocument);
            break;
        case "2":
            CRUD.UpdateJob(jsonDocument);
            break;
        case "3":
            CRUD.DeleteJob(jsonDocument);
            break;
        case "4":
            CRUD.GetEmployeeDetails(jsonDocument);
            break;
        default:
            Main(null);
            break;
    }
    Console.ReadLine();
}

The Whole Solution

using System;

namespace JsonCRUDTutorial
{
    class Program
    {
        private static readonly string jsonDocument = @"C:\Users\chs\source\repos\JsonCRUDTutorial\JsonCRUDTutorial\users.json";
        static void Main(string[] args)
        {
            Console.WriteLine("What would you like to do? : 1 - Add Job, 2 - Update Job, 3 - Delete Job, 4 - Select \n");
            var option = Console.ReadLine();
            switch (option)
            {
                case "1":
                    CRUD.AddJob(jsonDocument);
                    break;
                case "2":
                    CRUD.UpdateJob(jsonDocument);
                    break;
                case "3":
                    CRUD.DeleteJob(jsonDocument);
                    break;
                case "4":
                    CRUD.GetEmployeeDetails(jsonDocument);
                    break;
                default:
                    Main(null);
                    break;
            }
            Console.ReadLine();
        }
    }
}
using System;
using System.IO;
using System.Linq;
using Newtonsoft.Json.Linq;

namespace JsonCRUDTutorial
{
    public class CRUD
    {
        public static void GetEmployeeDetails(string jsonFilePath)
        {
            var json = File.ReadAllText(jsonFilePath);
            try
            {
                var jObject = JObject.Parse(json);

                if (jObject != null)
                {
                    Console.WriteLine("ID :" + jObject["id"].ToString());
                    Console.WriteLine("Full Name :" + jObject["fullname"].ToString());

                    var address = jObject["address"];
                    Console.WriteLine("Street :" + address["street"].ToString());
                    Console.WriteLine("City :" + address["city"].ToString());
                    Console.WriteLine("Zip :" + address["zip"]);
                    JArray jobsArray = (JArray)jObject["jobs"];
                    if (jobsArray != null)
                    {
                        foreach (var job in jobsArray)
                        {
                            Console.WriteLine("Job ID :" + job["jobid"]);
                            Console.WriteLine("Company Name :" + job["company"].ToString());
                        }

                    }
                    Console.WriteLine("Phone Number :" + jObject["phone"].ToString());
                    Console.WriteLine("Role :" + jObject["current-job-role"].ToString());

                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Could not read JSON data. More details: ", ex.Message);
                throw;
            }
        }

        public static void AddJob(string jsonFilePath)
        {
            Console.WriteLine("Enter Job ID : ");
            var jobId = Console.ReadLine();
            Console.WriteLine("\nEnter Job Name : ");
            var companyName = Console.ReadLine();

            var newJobMember = "{ 'jobid': " + jobId + ", 'company': '" + companyName + "'}";
            try
            {
                var json = File.ReadAllText(jsonFilePath);
                var jsonObj = JObject.Parse(json);
                var jobArrary = jsonObj.GetValue("jobs") as JArray;
                var newJob = JObject.Parse(newJobMember);
                jobArrary.Add(newJob);

                jsonObj["jobs"] = jobArrary;
                string newJsonResult = Newtonsoft.Json.JsonConvert.SerializeObject(jsonObj,
                                       Newtonsoft.Json.Formatting.Indented);
                File.WriteAllText(jsonFilePath, newJsonResult);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Add Error : " + ex.Message.ToString());
            }
        }

        public static void UpdateJob(string jsonFilePath)
        {
            string json = File.ReadAllText(jsonFilePath);

            try
            {
                var jObject = JObject.Parse(json);
                JArray jobsArrary = (JArray)jObject["jobs"];
                Console.Write("Enter Job ID to Update Job : ");
                var jobId = Convert.ToInt32(Console.ReadLine());

                if (jobId > 0)
                {
                    Console.Write("Enter new company name : ");
                    var companyName = Convert.ToString(Console.ReadLine());

                    foreach (var company in jobsArrary.Where(obj => obj["jobid"].Value<int>() == jobId))
                    {
                        company["company"] = !string.IsNullOrEmpty(companyName) ? companyName : "";
                    }

                    jObject["jobs"] = jobsArrary;
                    string output = Newtonsoft.Json.JsonConvert.SerializeObject(jObject, Newtonsoft.Json.Formatting.Indented);
                    File.WriteAllText(jsonFilePath, output);
                }
                else
                {
                    Console.Write("Invalid Job ID, Try Again!");
                    UpdateJob(jsonFilePath);
                }
            }
            catch (Exception ex)
            {

                Console.WriteLine("Update Error : " + ex.Message.ToString());
            }
        }

        public static void DeleteJob(string jsonFilePath)
        {
            var json = File.ReadAllText(jsonFilePath);
            try
            {
                var jObject = JObject.Parse(json);
                JArray jobsArrary = (JArray)jObject["jobs"];
                Console.Write("Enter Job ID to delete Job : ");
                var jobId = Convert.ToInt32(Console.ReadLine());

                if (jobId > 0)
                {
                    var jobName = string.Empty;
                    var jobToBeDeleted = jobsArrary.FirstOrDefault(obj => obj["jobid"].Value<int>() == jobId);

                    jobsArrary.Remove(jobToBeDeleted);

                    string output = Newtonsoft.Json.JsonConvert.SerializeObject(jObject, Newtonsoft.Json.Formatting.Indented);
                    File.WriteAllText(jsonFilePath, output);
                }
                else
                {
                    Console.Write("Invalid Job ID, Try Again.");
                    UpdateJob(jsonFilePath);
                }
            }
            catch (Exception)
            {

                throw;
            }
        }
    }
}
{
  "id": 1,
  "fullname": "John Doe",
  "address": {
    "street": "Jernbanegade 22",
    "city": "Svendborg",
    "zip": 5700
  },
  "jobs": [
    {
      "jobid": 77,
      "company": "ISS"
    },
    {
      "jobid": 89,
      "company": "DSB"
    },
    {
      "jobid": 22,
      "company": "GLS"
    }
  ],
  "phone": 896532417,
  "current-job-role": "Facility Manager"
}

Demo and Source Code

Below is a short video demonstrating each feature inside the application.

Read Employee Details

crud, Read
Option 4 – Read Employee Details

Add New Job

Option 1 – Add New Job

Update Existing Job

Option 2 – Update Job

Delete Existing Job

Option 3 – Delete Job

Source Code – Github Repo

Summary

In this C# JSON CRUD tutorial you have seen how to interact with JSON data directly inside the JSON file and how you can perform CRUD operations using C# code in collaboration with the Newtonsoft.Json package.

I hope the tutorial has been helpful to you and that you now are able to solve your problem. If you got any suggestions, comments, or questions, please let me know in the comments. As always – Happy coding! 🙂

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top