Fundamentals of JSON Serialization

Introduction to JSON

The JavaScript Object Notation, or JSON, is another technique to format the text in a document so that that text can be accessed and read by any system. You may remember that this is similar to the introduction we had with XML. This also means that JSON and XML have the same goal in terms of formatting a text-based document. One of the differences is that the contents of those documents are not formatted the same way, but they are created and used for the same goals.

Practical LearningPractical Learning: Introducing Geometric Accessories

  1. Start Microsoft Visual Studio
  2. Create a Windows Forms App named Exercise5

Introduction to JSON Serialization

JSON serialization consists of saving one or more values to a medium. As mentioned for XML serialization, to perform JSON serialization, you don't need to know anything about JavaScript and you don't need to know a single thing about JSON. The compiler will do everything for you as long as you give the right instructions through appropriate classes and methods.

To support JSON serialization, the .NET Framework provides various namespaces such as System.Text.Json and System.Text.Json.Serialization. These classes are defined in the System.Text.Json.dll assembly. The primary class used to perform serialization is named JsonSerializer:

public static class JsonSerializer

As you can see, JsonSerializer is a static class. This means that you will never declare a variable of it. This also means that all the members of the class are static. In fact, the JsonSerializer class has only methods. As a result, to perform an operation of that class, you will simply call the method you need.

Serializing in JSON

The JsonSerializer's method to serialize is named Serialize. To serialize something, call the JsonSerializer.Serialize() method and simply pass the value or object you want to save or write to a file.

A JsonSerializer.Serialize() method only indicates the value or object you want to save. To actually save the value or object, you need a class that performs input/output operations; that is, a class equipped to at least write some values to a medium. One of the available classes is the static File class. It is equipped with a method named WriteAllText. This method is available in two versions. The syntax of one of the versions is:

public static void WriteAllText (string path, string? contents);

This version takes two required arguments. The first argument is the name or path of the file in which the value(s) will be written. The second argument is the JsonSerializer object that has the value or object that must be written to the file.

A JSON Serialized File

When performing JSON serialization, you will indicate the that must hold the value(s) or object(s) you want to save. At a minimum, the file must have a name (and path) and it should have an extension. Normally, you can use any extension you want for your JSON serialized file, but this is a JSON file. Traditionally, a JSON file has the extention .json; so if you want, you can apply that extension to your files.

Serialization by Type

Serializing a Value

A value is a simple representation of a character, a number, a string, etc. To serialize a value, pass its value or its variable to the JsonSerializer.Serialize() method. Of course, call the File.WriteAllText() method. Pass the file or its path, followed by the returned value of the JsonSerializer.Serialize() call. Here is an example of serializing a simple value (in this case, a string):

using System.Text.Json;

namespace FourCornerSolutions
{
    public partial class SerializationDetails : Form
    {
        public SerializationDetails()
        {
            InitializeComponent();
        }

        private void btnSerialization_Click(object sender, EventArgs e)
        {
            string machine = "Refrigereator";

            string jsnMachine = JsonSerializer.Serialize(machine);
            File.WriteAllText(@"E:\Appliance Store\Machine.json", jsnMachine);
        }
    }
}

This would produce:

"Refrigereator"

As we usually mention, a variable is necessary when you plan to use it many times. If not, you may not need a certain variable in your project. As a result, the above could be written as follows:

private void btnRetension_Click(object sender, EventArgs e)
{
    string jsnMachine = JsonSerializer.Serialize("Refrigereator");
    File.WriteAllText(@"E:\Appliance Store\Machine3.json", jsnMachine);
}

or as follows:

private void btnRetension_Click(object sender, EventArgs e)
{
    File.WriteAllText(@"E:\Appliance Store\Machine4.json", JsonSerializer.Serialize("Refrigereator"));
}

Serializing an Object

As you may know already, an object is one value a group of values created from a class, a record, or a structure. Obviously, if you are planning to serialize an object, you must have a class, a record, or a structure. You can use a .NET built-in class or you can create you own. To serialize an object, you can first create it. Then pass that object to the JsonSerializer.Serialize() method and call the File.WriteAllText() as done for a value. Here is an example:

using System.Text.Json;

namespace FourCornerSolutions
{
    public partial class SerializationDetails : Form
    {
        public SerializationDetails()
        {
            InitializeComponent();
        }

        private void btnSerialization_Click(object sender, EventArgs e)
        {
            Tractor? machine = new Tractor()
            {
                ModelName    = "MW9724",
                EnginePower  = 21.5f,
                LiftCapacity = 754,
                MowerHeight  = 60,
                Price        = 13_050
            };

            string strTractor = @"E:\Four Corner Solutions\Machine.fcs";

            string jsnMachine = JsonSerializer.Serialize(machine);

            File.WriteAllText(strTractor, jsnMachine);
        }
    }

    public readonly record struct Tractor
    {
        public string? ModelName    { get; init; }
        public float   EnginePower  { get; init; }
        public int     LiftCapacity { get; init; }
        public int     MowerHeight  { get; init; }
        public decimal Price        { get; init; }
    }
}

This would produce:

{"ModelName":"MW9724","EnginePower":21.5,"LiftCapacity":754,"MowerHeight":60,"Price":13050}

Remember that a variable is necessary only if you are planning to use it more than once. The above code could have been written as follows:

private void btnSerialization_Click(object sender, EventArgs e)
{
    string jsnMachine = JsonSerializer.Serialize(new Tractor()
    {
        ModelName = "MW9724",
        EnginePower = 21.5f,
        LiftCapacity = 754,
        MowerHeight = 60,
        Price = 13_050
    });

    File.WriteAllText(@"E:\Four Corner Solutions\Machine.json", jsnMachine);
}

Or like this:

private void btnSerialization_Click(object sender, EventArgs e)
{
    File.WriteAllText(@"E:\Four Corner Solutions\Machine.json",
                      JsonSerializer.Serialize(new Tractor()
		                               {
                 			            ModelName = "MW9724",
                                                    EnginePower = 21.5f,
                                                    LiftCapacity = 754,
                                                    MowerHeight = 60,
                                                    Price = 13_050
               			               })
		    );
}

Serializing an Array or a List

An array is a list of values that all are of the same type. As a result, you can have an array of names or an array of numbers and you want to save that array. To proceed, you can first optionally create the needed array and assign it to a variable. Pass the array or its variable to the JsonSerializer.Serialize() method and call the File.WriteAllText() as we saw already. This can be done as follows:

using System.Text.Json;

namespace PayrollAndAccounting
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            string strTimeWorked = @"E:\Payroll and Accounting\TimeWorked.aps";

            double[] timesWorked = { 8.00d, 9.50d, 7.00d, 10.00d, 8.50d };

            string jsnTimeWorked = JsonSerializer.Serialize(timesWorked);
            File.WriteAllText(strTimeWorked, jsnTimeWorked);
        }
    }
}

This code would produce:

[8,9.5,7,10,8.5]

You may also want to serialize a list of objects. You can start by creating a list or array of objects, using any technique provided by the C# language. You can then pass that list to the JsonSerializer.Serialize() method and then call the File.WriteAllText() with its required arguments. Here is an example:

using System.Text.Json;

namespace FourCornerSolutions
{
    public partial class SerializationDetails : Form
    {
        public SerializationDetails()
        {
            InitializeComponent();
        }

        private void btnSerialization_Click(object sender, EventArgs e)
        {
            string strTractors = @"E:\Four Corner Solutions\Tractors.fcs";

            Tractor[] tractors =
            {
                new Tractor() { ModelName = "1023E", Price = 15_165.95m },
                new Tractor() { ModelName = "2032R", Price = 29_257.64m },
                new Tractor() { ModelName = "4052M", Price = 38_852.88m },
            };

            string jsTractors = JsonSerializer.Serialize(tractors);
            File.WriteAllText(strTractors, jsTractors);
        }
    }

    public readonly record struct Tractor
    {
        public string? ModelName { get; init; }
        public decimal Price     { get; init; }
    }
}

This code would produce:

[{"ModelName":"1023E","Price":15165.95},{"ModelName":"2032R","Price":29257.64},{"ModelName":"4052M","Price":38852.88}]

Details on JSON Serialization

The Type to Serialize

Earlier, we saw that, to serialize a value, an object, or a list, you can call the JsonSerializer.Serialize() method to which you would pass the value, the object, or the list you want to save. If you want, and as we saw with XML serialization, you can indicate the type of value, object, or list you want to save. To do this, pass a second argument to the JsonSerializer.Serialize() method. Use the typeof() operator to indicate the type. This can be done as follows:

using System.Text.Json;

namespace FourCornerSolutions
{
    public partial class SerializationDetails : Form
    {
        public SerializationDetails()
        {
            InitializeComponent();
        }

        private void btnSerialization_Click(object sender, EventArgs e)
        {
            string machine = "Refrigereator";

            string jsnMachine = JsonSerializer.Serialize(machine, typeof(string));
            File.WriteAllText(@"E:\Appliance Store\Machine.json", jsnMachine);
        }
    }
}

Introduction to JSON Options

Consider the following JSON serialization code:

using System.Text.Json;

namespace FourCornerSolutions
{
    public partial class SerializationDetails : Form
    {
        public SerializationDetails()
        {
            InitializeComponent();
        }

        private void btnSerialization_Click(object sender, EventArgs e)
        {
            string strAppliances = @"E:\Appliance Store\Appliances.json";

            Appliance[] appliances =
            {
                new Appliance() { Make = "Instant Pot", Price = 82.37, ItemNumber = 973947, Type = "RiceCooker",
                                  Name = "Duo 7-in-1 Electric Pressure Cooker, Slow Cooker, Rice Cooker, and more",
                                  Wattage = 1000 },
                new Appliance() { Name = "Cool Touch Sides Easy to Clean Nonstick Basket",
                                  Make = "Hamilton Beach", Price = 49.85, Type = "Deep Fryer",
                                  ItemNumber = 202793 },
                new Appliance() { Price = 58.77, ItemNumber = 828628, Wattage = 700,
                                  Make = "Oster", Type = "Blender",
                                  Name = "6-Cup Glass Jar 12-Speed Blender", }
            };

            string jsAppliances = JsonSerializer.Serialize(appliances, typeof(Appliance[]));
            File.WriteAllText(strAppliances, jsAppliances);
        }
    }

    public record class Appliance
    {
        public long    ItemNumber { get; set; }
        public string? Type       { get; set; }
        public string? Make       { get; set; }
        public string? Name       { get; set; }
        public int     Wattage    { get; set; }
        public double  Price      { get; set; }
    }
}

This code would produce:

[{"ItemNumber":973947,"Type":"RiceCooker","Make":"Instant Pot","Name":"Duo 7-in-1 Electric Pressure Cooker, Slow Cooker, Rice Cooker, and more","Wattage":1000,"Price":82.37},{"ItemNumber":202793,"Type":"Deep Fryer","Make":"Hamilton Beach","Name":"Cool Touch Sides Easy to Clean Nonstick Basket","Wattage":0,"Price":49.85},{"ItemNumber":828628,"Type":"Blender","Make":"Oster","Name":"6-Cup Glass Jar 12-Speed Blender","Wattage":700,"Price":58.77}]

In our introductions to both XML serialization and JSON serialization, we stated that you need to know neither XML, nor JavaScript, nor JSON to perform serializtion. That remains true. Still, there is a way the compiler, or rather the parser, formats the serialized document. In some cases, if you want, you can assist the compiler with some details. These are options that are not required but can be helpful (even useful) at times. To assist you with options you can apply when performing JSON serialization, the .NET Framework provides a sealed class named JsonSerializerOptions:

public sealed class JsonSerializerOptions

The JsonSerializerOptions class has three constructors. You can use one of the constructors to declare a JsonSerializerOptions variable and initialize it. One of the constructors is the default:

public JsonSerializerOptions();

Earlier, we saw that, to serialize a value, an object, or a list, you can call the JsonSerializer.Serialize() method to which you would pass the value, the object, or the list you want to save. Actually, the JsonSerializer.Serialize() method is available in many (12) versions. One of the versions of this method uses the following syntax:

public static string Serialize(object? value, Type inputType, System.Text.Json.JsonSerializerOptions? options = default);

This version of the JsonSerializer.Serialize() method takes three arguments. Only the first argument is required. The other two arguments are optional. The first argument is the value or object you want to save or write to a file. As we saw already, the second argument specifies the type you want to serialize. After creating a JsonSerializerOptions object you can pass it as the third argument to the JsonSerializer.Serialize() method. Remember that this third argument is optional.

The JsonSerializerOptions class provides many options. Many of those opions suggest that you know JSON (and how arrays are used in JavaScript), but we have already promised (and maintain) that you don't need to know JSON (nor JavaScript) in order to follow this lesson. As a result, we will review only one option. Most of the other options can be applied easily.

Indenting a JSON Serialized Document

If you are planning to physically (or manually) open a JSON serialized document to humanly read its content, you may want the items (traditionally called nodes) in it to be written on different lines and, in fact, to be indented. To let you provide this information to the compiler, the JsonSerializerOptions class is equipped with a Boolean property named WriteIndented:

public bool WriteIndented { get; set; }

By default, this property holds a False value. If you want the items in your JSON serialized document to be written on different lines with distinguished white spaces and appropriately indented, set the value of this property to True. This can be done as follows:

using System.Text.Json;

namespace FourCornerSolutions
{
    public partial class SerializationDetails : Form
    {
        public SerializationDetails()
        {
            InitializeComponent();
        }

        private void btnSerialization_Click(object sender, EventArgs e)
        {
            string strAppliances = @"E:\Appliance Store\Appliances7.json";

            Appliance[] appliances =
            {
                new Appliance() { Make = "Instant Pot", Price = 82.37, ItemNumber = 973947, Type = "RiceCooker",
                                  Name = "Duo 7-in-1 Electric Pressure Cooker, Slow Cooker, Rice Cooker, and more",
                                  Wattage = 1000 },
                new Appliance() { Name = "Cool Touch Sides Easy to Clean Nonstick Basket",
                                  Make = "Hamilton Beach", Price = 49.85, Type = "Deep Fryer",
                                  ItemNumber = 202793 },
                new Appliance() { Price = 58.77, ItemNumber = 828628, Wattage = 700,
                                  Make = "Oster", Type = "Blender",
                                  Name = "6-Cup Glass Jar 12-Speed Blender", }
            };

            JsonSerializerOptions options = new JsonSerializerOptions();
            options.WriteIndented = true;

            string jsAppliances = JsonSerializer.Serialize(appliances, typeof(Appliance[]), options);
            File.WriteAllText(strAppliances, jsAppliances);
        }
    }

    public record class Appliance
    {
        public long    ItemNumber { get; set; }
        public string? Type       { get; set; }
        public string? Make       { get; set; }
        public string? Name       { get; set; }
        public int     Wattage    { get; set; }
        public double  Price      { get; set; }
    }
}

This would produce:

[
  {
    "ItemNumber": 973947,
    "Type": "RiceCooker",
    "Make": "Instant Pot",
    "Name": "Duo 7-in-1 Electric Pressure Cooker, Slow Cooker, Rice Cooker, and more",
    "Wattage": 1000,
    "Price": 82.37
  },
  {
    "ItemNumber": 202793,
    "Type": "Deep Fryer",
    "Make": "Hamilton Beach",
    "Name": "Cool Touch Sides Easy to Clean Nonstick Basket",
    "Wattage": 0,
    "Price": 49.85
  },
  {
    "ItemNumber": 828628,
    "Type": "Blender",
    "Make": "Oster",
    "Name": "6-Cup Glass Jar 12-Speed Blender",
    "Wattage": 700,
    "Price": 58.77
  }
]

Serializing Embedded Objects

Normally, in C#, a property of an object can be of any type. For example, a property can be of a class type. When creating an object of that type, make sure you initialize each property based on its type. You can then perform serialization exactly as done with values and other objects so far. Here is an example:

using System.Text.Json;

namespace FourCornerSolutions
{
    public partial class CommercialSales : Form
    {
        public SerializationDetails()
        {
            InitializeComponent();
        }

        private void btnSerialization_Click(object sender, EventArgs e)
        {
            string strTractors = @"E:\Four Corner Solutions\Tractor.json";

            Tractor machine = new Tractor()
            {
                ItemNumber = 249_580,
                ModelName = "1023E",
                LiftCapacity = new Capacity() { Kilogram = 344, Pounds = 758 },
                CruiseControl = CruiseControl.True,
                Engine = new Engine() { Power = 21.5f, Type = EngineType.Diesel, Cylinders = 3 },
                Price = 15_165.95m
            };

            JsonSerializerOptions options = new JsonSerializerOptions();
            options.WriteIndented = true;

            string jsAppliances = JsonSerializer.Serialize(machine, typeof(Tractor), options);
            File.WriteAllText(strTractors, jsAppliances);
        }
    }

    public enum   EngineType    { Gas, Diesel, Electric, Unknown }
    public enum   CruiseControl { No, True, Standard, Optional, NotAvailable, Unknown }

    public struct Capacity
    {
        public int Kilogram { get; set; }
        public int Pounds   { get; set; }
    }

    public struct Engine
    {
        public float      Power     { get; set; }
        public EngineType Type      { get; set; }
        public int        Cylinders { get; set; }
    }

    public record class Tractor
    {
        public long          ItemNumber    { get; set; }
        public string?       ModelName     { get; init; }
        public Capacity      LiftCapacity  { get; init; }
        public CruiseControl CruiseControl { get; init; }
        public Engine        Engine        { get; init; }
        public decimal       Price         { get; init; }
    }
}

This would produce:

{
  "ItemNumber": 249580,
  "ModelName": "1023E",
  "LiftCapacity": {
    "Kilogram": 344,
    "Pounds": 758
  },
  "CruiseControl": 1,
  "Engine": {
    "Power": 21.5,
    "Type": 1,
    "Cylinders": 3
  },
  "Price": 15165.95
}

In the same way, you can create a list of objects from a class, a record, or a structure that contains members that, in turn, are of class, record, or object types. Here is an example:

using System.Text.Json;

namespace FourCornerSolutions
{
    public partial class CommercialSales : Form
    {
        public CommercialSales()
        {
            InitializeComponent();
        }

        private void btnSerialization_Click(object sender, EventArgs e)
        {
            string strTractors = @"E:\Four Corner Solutions\Tractors.json";

            Tractor[] tractors =
            {
                new Tractor()
                {
                    ItemNumber = 249_580, ModelName = "1023E",
                    LiftCapacity = new Capacity() { Kilogram = 344, Pounds = 758 },
                    CruiseControl = CruiseControl.True,
                    Engine = new Engine() { HorsePower = 21.5f, Type = EngineType.Diesel, Cylinders = 3 },
                    Price = 15_165.95m
                },
                new Tractor()
                {
                    ItemNumber = 508_404, ModelName = "4052M",
                    LiftCapacity = new Capacity() { Kilogram = 1135, Pounds = 2500 },
                    CruiseControl = CruiseControl.Optional,
                    Engine = new Engine() { HorsePower = 50.8f, Type = EngineType.Diesel, Cylinders = 4 },
                    Price = 37_945m 
                },
                new Tractor()
                {
                    ItemNumber = 927_497, ModelName = "2025R",
                    LiftCapacity = new Capacity() { Kilogram = 415,  Pounds = 915 } ,
                    CruiseControl = CruiseControl.Standard,
                    Engine = new Engine() { HorsePower = 23.9f, Type = EngineType.Diesel, Cylinders = 3 },
                    Price = 22_755m
                },
            };

            JsonSerializerOptions options = new JsonSerializerOptions();
            options.WriteIndented = true;

            string jsTractors = JsonSerializer.Serialize(tractors, typeof(Tractor[]), options);
            File.WriteAllText(strTractors, jsTractors);
        }
    }

    public enum   EngineType    { Gas, Diesel, Electric, Unknown }
    public enum   CruiseControl { No, True, Standard, Optional, NotAvailable, Unknown }

    public struct Capacity
    {
        public int Kilogram { get; set; }
        public int Pounds   { get; set; }
    }

    public struct Engine
    {
        public float      HorsePower { get; set; }
        public EngineType Type       { get; set; }
        public int        Cylinders  { get; set; }
    }

    public record class Tractor
    {
        public long          ItemNumber    { get; set; }
        public string?       ModelName     { get; init; }
        public Capacity      LiftCapacity  { get; init; }
        public CruiseControl CruiseControl { get; init; }
        public Engine        Engine        { get; init; }
        public decimal       Price         { get; init; }
    }
}

This would produce:

[
  {
    "ItemNumber": 249580,
    "ModelName": "1023E",
    "LiftCapacity": {
      "Kilogram": 344,
      "Pounds": 758
    },
    "CruiseControl": 1,
    "Engine": {
      "HorsePower": 21.5,
      "Type": 1,
      "Cylinders": 3
    },
    "Price": 15165.95
  },
  {
    "ItemNumber": 508404,
    "ModelName": "4052M",
    "LiftCapacity": {
      "Kilogram": 1135,
      "Pounds": 2500
    },
    "CruiseControl": 3,
    "Engine": {
      "HorsePower": 50.8,
      "Type": 1,
      "Cylinders": 4
    },
    "Price": 37945
  },
  {
    "ItemNumber": 927497,
    "ModelName": "2025R",
    "LiftCapacity": {
      "Kilogram": 415,
      "Pounds": 915
    },
    "CruiseControl": 2,
    "Engine": {
      "HorsePower": 23.9,
      "Type": 1,
      "Cylinders": 3
    },
    "Price": 22755
  }
]

JSON Deserialization

Introduction

While serialiazation is the process of sending one or more values to a stream, deserialiazation consists of reading values that exist in a stream. We already know that, in serialiazation, the values are written in a certain way and, whether in XML serialization or JSON serialiazation, the document is appropriately formatted. As a result, when it comes time to deserialize, that is to read the document, the compiler, actually the parser, has to be able to read it. If you had created the document through JSON serialization, the compiler would make sure the sections in the document are appropriately created. If you created the JSON document manually, which you are allowed to do (in both XML serialiazation and JSON serialiazation), if you make a mistake or write something in a way the parser cannot read, the compiler would throw an exception (various types of exceptions are available, for different reasons.

Before deserializing, you must identify the file that holds the values you want to get. You can start by declaring a string variable and initialize it with the file name or path. You can then read the document. As we know already, the .NET Framework provides many classes for file processing, such as File. Remember that JSON serialization produces a text-based document. To let you read text from a file, the File class is equipped with a method named File. It is available in two versions. The syntax of one of them is:

public static string ReadAllText(string path);

This method takes one argument as the name of a file or its path. When this method is called, it reads the text from the file passed as argument. If the method succeeds, it returns the whole text that was read. This can be done as follows:

private void btnDeserialization_Click(object sender, EventArgs e)
{
    string strMachine = @"E:\Appliance Store\Appliance.json";

    string result = File.ReadAllText(strMachine);
}

Deserializing with JSON

To support JSON deserialiazation, the JsonSerializer class is equipped with a method named Deserialize. It is available in many (32) versions. One of the syntaxes of the JsonSerializer.Deserialize() method is:

public static TValue? Deserialize<TValue>(string json, System.Text.Json.JsonSerializerOptions? options = default);

This method takes one required and one optional arguments. The first argument is the text to read. It can be the value returned by a File.ReadAllText() call. Therefore, you can pass the variable of that call to JsonSerializer.Deserialize<>(). If the JsonSerializer.Deserialize<>() method succeeds in reading the document, it returns the text produced by the file reader, such as the value returned by a call to the File.ReadAllText() method, but the value is produced in JSON format.

Deserialization by Type

Deserialization a Value

The simplest thing that can be deserialized is a regular value such as a number, a symbol, a string, a Boolean representation, etc. If you are reading a regular value from the document, you can declare a variable of that value's type and assign the JsonSerializer.Deserialize<>() call to it. When calling the JsonSerializer.Deserialize<>() method, the compiler needs to know the type of value you are reading. Therefore, you must pass the parameter type that is the same type as the variable to which you are assigning the JsonSerializer.Deserialize() call. This can be done as follows:

using System.Text.Json;

namespace ApplianceStore
{
    public partial class Exercise : Form
    {
        public Exercise ()
        {
            InitializeComponent();
        }

        private void btnSerialize_Click(object sender, EventArgs e)
        {
            string machine = "Refrigereator";

            string jsnMachine = JsonSerializer.Serialize(machine);
            File.WriteAllText(@"E:\Appliance Store\Appliance.json", jsnMachine);
        }

        private void btnDeserialize_Click(object sender, EventArgs e)
        {
            string strMachine = @"E:\Appliance Store\Appliance.json";

            string result = File.ReadAllText(strMachine);

            string jsnMachine = JsonSerializer.Deserialize<string>(result)!;

            MessageBox.Show(result);
        }
    }
}

Deserializing an Object

If you had saved an object in a file and you want to get that object using JSON deserialization, declare a variable of the class, record, or structure of that object and assign a call to JsonSerializer.Deserialize<>() to that variable. Specify the parameter type as the class, record, or structure of the object you are getting. Pass the argument as a text returned from a call to File.ReadAllText(). If the File.ReadAllText() succeeds in reading all the text in the document and passes that text to the JsonSerializer.Deserialize<>() method, you can use the variable you had declared for the object to get each value you want. This can be done as follows:

using System.Text.Json;

namespace Exercises
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void btnSerialization_Click(object sender, EventArgs e)
        {
            Tractor? machine = new Tractor()
            {
                ModelName = "MW9724",
                EnginePower = 21.5f,
                LiftCapacity = 754,
                MowerHeight = 60,
                Price = 13_050
            };

            string strTractor = @"E:\Four Corner Solutions\Machine.fcs";

            JsonSerializerOptions options = new();

            options.WriteIndented = true;
            string jsnMachine = JsonSerializer.Serialize(machine, typeof(Tractor), options);

            File.WriteAllText(strTractor, jsnMachine);
        }

        private void btnDeserialization_Click(object sender, EventArgs e)
        {
            string strTractor = @"E:\Four Corner Solutions\Machine.fcs";

            string result = File.ReadAllText(strTractor);

            Tractor jsnMachine = JsonSerializer.Deserialize<Tractor>(result)!;

            txtModelName.Text = jsnMachine.ModelName;
            txtEnginePower.Text = jsnMachine.EnginePower.ToString("n");
            txtLiftCapacity.Text = jsnMachine.LiftCapacity.ToString();
            txtMowerHeight.Text = jsnMachine.MowerHeight.ToString();
            txtPrice.Text = jsnMachine.Price.ToString();
        }
    }

    public readonly record struct Tractor
    {
        public string? ModelName { get; init; }
        public float EnginePower { get; init; }
        public int LiftCapacity { get; init; }
        public int MowerHeight { get; init; }
        public decimal Price { get; init; }
    }
}

Deserializing a List

Imagine you have a list of objects that you want to save with JSON serialization. As we learned already, this can be done as follows:

using System.Text.Json;

namespace ApplianceStore
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void btnSerialization_Click(object sender, EventArgs e)
        {
            string strAppliances = @"E:\Appliance Store\Appliances.json";

            Appliance[] appliances =
            {
                new Appliance() { ItemNumber = 973_947, Make = "Instant Pot", Price = 82.37, Type = "RiceCooker",
                                  Name = "Duo 7-in-1 Electric Pressure Cooker, Slow Cooker, Rice Cooker, and more",
                                  Wattage = 1000 },
                new Appliance() { Make = "Hamilton Beach", Price = 49.85, Type = "Deep Fryer",
                                  Name = "Cool Touch Sides Easy to Clean Nonstick Basket",
                                  ItemNumber = 202_793 },
                new Appliance() { Price = 58.77, ItemNumber = 828628, Wattage = 700,
                                  Make = "Oster", Type = "Blender",
                                  Name = "6-Cup Glass Jar 12-Speed Blender", },
                new Appliance() { Wattage = 1000, Type = "Pressure Cooker",
                                  Make = "Cuisinart", ItemNumber = 620_741, Price = 106.48,
                                  Name = "6-Quart Electric Pressure Cooker", },
                new Appliance() { Price = 31.15, ItemNumber = 404_808, 
                                  Make = "Cuisinart", Type = "Toaster",
                                  Name = "2-Slice Compact Plastic Toaster", },
            };

            string jsAppliances = JsonSerializer.Serialize(appliances, typeof(Appliance[]));
            File.WriteAllText(strAppliances, jsAppliances);
        }
    }

    public record class Appliance
    {
        public long    ItemNumber { get; set; }
        public string? Type       { get; set; }
        public string? Make       { get; set; }
        public string? Name       { get; set; }
        public int     Wattage    { get; set; }
        public double  Price      { get; set; }
    }
}

When the file is save, text in it is formatted as JSON. You can then use JSON deserialization to get the objects in that file. To do this, declare a variable of the list, such as an array variable. Assign JsonSerializer.Deserialize<>() to it. Specify the parameter type as the type of the list, su as the array type. Pass a string returned from File.ReadAllText(). In this description, the JsonSerializer.Deserialize<>() would return the list of objects in the file. You can then use the list as you judge it necessary. This can be done as follows:

using System.Text.Json;

namespace ApplianceStore
{
    public partial class AppliancesInventory : Form
    {
        public AppliancesInventory()
        {
            InitializeComponent();
        }

        private void AppliancesInventory_Load(object sender, EventArgs e)
        {
            string strAppliances = @"E:\Appliance Store\Appliances.json";

            string result = File.ReadAllText(strAppliances);

            Appliance[] appliances = JsonSerializer.Deserialize<Appliance[]>(result)!;

            foreach (Appliance appliance in appliances)
            {
                ListViewItem lviAppliance = new ListViewItem(appliance.ItemNumber.ToString());

                lviAppliance.SubItems.Add(appliance.Type);
                lviAppliance.SubItems.Add(appliance.Make);
                lviAppliance.SubItems.Add(appliance.Name);
                lviAppliance.SubItems.Add(appliance.Wattage.ToString());
                lviAppliance.SubItems.Add(appliance.Price.ToString("n"));
                lvwAppliances.Items.Add(lviAppliance);
            }
        }
    }
}

This would produce:

Deserializing a List

If the class, record, or structure contains at least one property that is of class, record, or structure type, you can use the same steps to JSON deserialize the file. When accessing an object of the resulting list, you can access the property that is of vlass, record, or structure type and access its own properties. This can be donoe as follows:

using System.Text.Json;

namespace Exercises
{
    public partial class IndustrialVehicles : Form
    {
        public IndustrialVehicles()
        {
            InitializeComponent();
        }

        private void btnSaveTractors_Click(object sender, EventArgs e)
        {
            string strTractors = @"E:\Four Corner Solutions\Tractors.json";

            Tractor[] tractors =
            {
                new Tractor()
                {
                    ItemNumber = 249_580, ModelName = "1023E",
                    CruiseControl = CruiseControl.True, Price = 15_165.95m,
                    LiftCapacity = new Capacity() { Kilogram = 344, Pounds = 758 },
                    Engine = new Engine() { HorsePower = 21.5f, Type = EngineType.Diesel, Cylinders = 3 },
                },
                new Tractor()
                {
                    Price = 25_285.45m, ItemNumber = 447_394, ModelName = "3032E",
                    LiftCapacity = new Capacity() { Kilogram = 615,  Pounds = 1356 } ,
                    CruiseControl = CruiseControl.Optional,
                    Engine = new Engine() { HorsePower = 25f, Type = EngineType.Diesel, Cylinders = 3 },
                },
                new Tractor()
                {
                    Price = 22_135.65m, ItemNumber = 739_749, ModelName = "3025E",
                    LiftCapacity = new Capacity() { Kilogram = 615,  Pounds = 1356 } ,
                    CruiseControl = CruiseControl.Optional,
                    Engine = new Engine() { HorsePower = 24.4f, Type = EngineType.Diesel, Cylinders = 3 },
                },
                new Tractor()
                {
                    CruiseControl = CruiseControl.Optional,
                    ItemNumber = 508_404, ModelName = "4052M", Price = 37_945.55m,
                    LiftCapacity = new Capacity() { Kilogram = 1135, Pounds = 2500 },
                    Engine = new Engine() { HorsePower = 50.8f, Type = EngineType.Diesel, Cylinders = 4 }
                },
                new Tractor()
                {
                    Price = 22_755.75m, ItemNumber = 927_497, ModelName = "2025R",
                    LiftCapacity = new Capacity() { Kilogram = 415,  Pounds = 915 } ,
                    CruiseControl = CruiseControl.Standard,
                    Engine = new Engine() { HorsePower = 23.9f, Type = EngineType.Diesel, Cylinders = 3 },
                },
            };

            JsonSerializerOptions options = new JsonSerializerOptions();
            options.WriteIndented = true;

            string jsTractors = JsonSerializer.Serialize(tractors, typeof(Tractor[]), options);
            File.WriteAllText(strTractors, jsTractors);
        }

        private void btnOpenTractors_Click(object sender, EventArgs e)
        {
            string strTractors = @"E:\Four Corner Solutions\Tractors.json";

            string result = File.ReadAllText(strTractors);

            Tractor[] tractors = JsonSerializer.Deserialize<Tractor[]>(result)!;

            foreach (Tractor vehicle in tractors)
            {
                ListViewItem lviAppliance = new ListViewItem(vehicle.ItemNumber.ToString());

                lviAppliance.SubItems.Add(vehicle.ModelName);
                lviAppliance.SubItems.Add(vehicle.LiftCapacity.Kilogram + " kgs, " + vehicle.LiftCapacity.Pounds + " lbs");
                lviAppliance.SubItems.Add(vehicle.CruiseControl.ToString());
                lviAppliance.SubItems.Add(vehicle.Engine.HorsePower + " hp, Engine Type: " + vehicle.Engine.Type + ", " + vehicle.Engine.Cylinders + " Cylinders");
                lviAppliance.SubItems.Add(vehicle.Price.ToString("n"));
                lvwAppliances.Items.Add(lviAppliance);
            }
        }
    }

    public enum EngineType    { Gas, Diesel, Electric, Unknown }
    public enum CruiseControl { No, True, Standard, Optional, NotAvailable, Unknown }

    public struct Capacity
    {
        public int           Kilogram      { get; init; }
        public int           Pounds        { get; init; }
    }

    public struct Engine
    {
        public float         HorsePower    { get; init; }
        public EngineType    Type          { get; init; }
        public int           Cylinders     { get; init; }
    }

    public record class Tractor
    {
        public long          ItemNumber    { get; init; }
        public string?       ModelName     { get; init; }
        public Capacity      LiftCapacity  { get; init; }
        public CruiseControl CruiseControl { get; init; }
        public Engine        Engine        { get; init; }
        public decimal       Price         { get; init; }
    }
}

This would produce:

Deserializing a List

Practical LearningPractical Learning: Ending the Lesson


Previous Copyright © 2010-2024, FunctionX Monday 28 November 2022 Next