Home > Software design >  Json to multiple objects and using values to enumerate
Json to multiple objects and using values to enumerate

Time:11-29

I have a small server shop that doesn't really need a database, so I decided to use a json file instead The json file have multiple objects.

{
  "Windows": [
    {
      "Entry": {
        "Price": "900",
        "Cores": "2 vCPU",
        "RAM": "4GB vRAM",
        "Disk": "128GB Disk",
        "OS": "Windows Server"
      },
      "Medium": {
        "Price": "1400",
        "Cores": "4 vCPU",
        "RAM": "8GB vRAM",
        "Disk": "512GB Disk",
        "OS": "Windows Server"
      },
      "High": {
        "Price": "2000",
        "Cores": "8 vCPU",
        "RAM": "16GB vRAM",
        "Disk": "1TB Disk",
        "OS": "Windows Server"
      }
    }
  ],

  "Linux": [
    {
      "Entry": {
        "Price": "700",
        "Cores": "2 vCPU",
        "RAM": "4GB vRAM",
        "Disk": "128GB Disk",
        "OS": "Linux"
      },
      "Medium": {
        "Price": "1200",
        "Cores": "4 vCPU",
        "RAM": "8GB vRAM",
        "Disk": "512GB Disk",
        "OS": "Linux"
      },
      "High": {
        "Price": "1800",
        "Cores": "8 vCPU",
        "RAM": "16GB vRAM",
        "Disk": "1TB Disk",
        "OS": "Linux"
      }
    }
  ]
}

I want to break the objects in its individual parts to use it in a page where I can enumerate through the values, below is my approach to get the name of a property and its values

public Dictionary<string, object> GetServers()
{
    using (var file = new StreamReader(*file directory*))
    {
         //Deserialize the file file into the RootObject
         var json = file.ReadToEnd();
         var obj = JsonSerializer.Deserialize<Rootobject>(json);

         //Read each object of the json file into a dictionary with the object key and the preceding values which is another object. 
         Type type = obj.GetType();
         PropertyInfo[] properties = type.GetProperties();
         var servers = new Dictionary<string, object>();

         foreach (var property in properties)
         {
             servers.Add(property.Name, property.GetValue(obj));
         }

         return servers;
    }
}

Here is the root object

public class Rootobject
{
    public Window[] Windows { get; set; }
    public Linux[] Linux { get; set; }
}

public class Window
{
    public Entry Entry { get; set; }
    public Medium Medium { get; set; }
    public High High { get; set; }
}

public class Entry
{
    public string Price { get; set; }
    public string Cores { get; set; }
    public string RAM { get; set; }
    public string Disk { get; set; }
    public string OS { get; set; }
}

public class Medium
{
    public string Price { get; set; }
    public string Cores { get; set; }
    public string RAM { get; set; }
    public string Disk { get; set; }
    public string OS { get; set; }
}

public class High
{
    public string Price { get; set; }
    public string Cores { get; set; }
    public string RAM { get; set; }
    public string Disk { get; set; }
    public string OS { get; set; }
}

public class Linux
{
    public Entry1 Entry { get; set; }
    public Medium1 Medium { get; set; }
    public High1 High { get; set; }
}

public class Entry1
{
    public string Price { get; set; }
    public string Cores { get; set; }
    public string RAM { get; set; }
    public string Disk { get; set; }
    public string OS { get; set; }
}

public class Medium1
{
    public string Price { get; set; }
    public string Cores { get; set; }
    public string RAM { get; set; }
    public string Disk { get; set; }
    public string OS { get; set; }
}

public class High1
{
    public string Price { get; set; }
    public string Cores { get; set; }
    public string RAM { get; set; }
    public string Disk { get; set; }
    public string OS { get; set; }
}

I want to enumerate through the windows server and split the objects.

So lets say I create a Page consisting of the servers that I offer I want to enumerate through all the windows as well as the linux servers

Example of entry level server

foreach(var server in Root)
{
    <div >
        <div>
            <div >
                <div >
                    //Server Type (Windows or Linux)
                    <h4 >@server.Key</h4>
                </div>
                <div  id="card1">
                    //Server details 
                    <h3 >@server.Value.Price</h3>
                    <p id="cores">@server.Value.Cores</p>
                    <p id="ram">@server.Value.RAM</p>
                    <p id="disk">@server.Value.Disk</p>
                    <p id="os"><i ></i>@server.Value.OS</p>
                </div>
                <button >
                    View
                </button>
            </div>
        </div>
    </div>
}

An example of 1 card

Card one example

But no matter what I do, I cant seem to find a solution of what I want Any help will be greatly appreciated

CodePudding user response:

I don't get why you are enumerating the properties. I would do something like this:

var rootObject = JsonSerializer.Deserialize<Rootobject>("JSON STRING");
List<object> servers = new List<object>();
servers.AddRange(rootObject.Windows);
servers.AddRange(rootObject.Linux);

Now you have both servers in one list.

Since both Windows and Linux are sharing the same properties, I would also declare an interface for them like this:

public interface IComputer 
{
    Entry Entry { get; set; }
    Medium Medium { get; set; }
    High High { get; set; }
}

Then you can replace List<object> with List<IComputer>. The benefit of this is you can access all properties easily with Intellisense.

Your classes will look like this then:

public class Rootobject
{
    public Window[] Windows { get; set; }
    public Linux[] Linux { get; set; }
}

public class Window : IComputer
{
    public Entry Entry { get; set; }
    public Medium Medium { get; set; }
    public High High { get; set; }
}

public class Linux : IComputer
{
    public Entry Entry { get; set; }
    public Medium Medium { get; set; }
    public High High { get; set; }
}

public class Entry
{
    public string Price { get; set; }
    public string Cores { get; set; }
    public string RAM { get; set; }
    public string Disk { get; set; }
    public string OS { get; set; }
}

public class Medium
{
    public string Price { get; set; }
    public string Cores { get; set; }
    public string RAM { get; set; }
    public string Disk { get; set; }
    public string OS { get; set; }
}

public class High
{
    public string Price { get; set; }
    public string Cores { get; set; }
    public string RAM { get; set; }
    public string Disk { get; set; }
    public string OS { get; set; }
}

CodePudding user response:

First I'd get rid of the redundant classes you use to deserialize your json, Enty, Medium and High all have the same properties for both Windows and Linux so they could all be of the same type, I'll just call it Specs for now.

Same goes for Windows and Linux, they could both be the same type. Let's just say Platform and give them a property for the platform name.

That leaves you with

public class Rootobject
{
    public Platform[] Platforms { get; set; }
}

public class Platform
{
    public string Name { get; set; }
    public Specs Entry { get; set; }
    public Specs Medium { get; set; }
    public Specs High { get; set; }
}

public class Specs
{
    public string Price { get; set; }
    public string Cores { get; set; }
    public string RAM { get; set; }
    public string Disk { get; set; }
    public string OS { get; set; }
}

You'll have to do some small adjustments to your json

{
  "Platforms": [
    {
      "Name": "Windows",
      "Entry": {
        "Price": "900",
        "Cores": "2 vCPU",
        "RAM": "4GB vRAM",
        "Disk": "128GB Disk",
        "OS": "Windows Server"
      },
      "Medium": {
        "Price": "1400",
        "Cores": "4 vCPU",
        "RAM": "8GB vRAM",
        "Disk": "512GB Disk",
        "OS": "Windows Server"
      },
      "High": {
        "Price": "2000",
        "Cores": "8 vCPU",
        "RAM": "16GB vRAM",
        "Disk": "1TB Disk",
        "OS": "Windows Server"
      }      
    },
    {
      "Name": "Linux",
      "Entry": {
        "Price": "700",
        "Cores": "2 vCPU",
        "RAM": "4GB vRAM",
        "Disk": "128GB Disk",
        "OS": "Linux"
      },
      "Medium": {
        "Price": "1200",
        "Cores": "4 vCPU",
        "RAM": "8GB vRAM",
        "Disk": "512GB Disk",
        "OS": "Linux"
      },
      "High": {
        "Price": "1800",
        "Cores": "8 vCPU",
        "RAM": "16GB vRAM",
        "Disk": "1TB Disk",
        "OS": "Linux"
      }
    } 
  ] 
}

Also you can directly iterate your Platform array in your razor code and display their properties. There's no real point to doing it through reflection unless you want to be able to add properties to your classes later on without changing the GUI, which does not seem to be what you're trying to do.

PS: I'd reevaluate if the shop really does not need some sort of database in the future. Requirements change and a bunch of json files might get messy later on.

CodePudding user response:

you can iterate using this algorithm, and you only need one class

var servers = System.Text.Json.JsonSerializer
      .Deserialize<Dictionary<string, Dictionary<string, Entry>[]>>(json);

    foreach (var server in servers)
    {
        Console.WriteLine(server.Key); // "windows" or "lunix"
        foreach (var os in server.Value)
        {
            foreach (var entry in os)
            {
                Console.WriteLine(entry.Key); // "entry","medium", or "high"

            Console.WriteLine(entry.Value.Price);
            Console.WriteLine(entry.Value.Cores);
            //....
            }
        }
    }

public class Entry
{
    public string Price { get; set; }
    public string Cores { get; set; }
    public string RAM { get; set; }
    public string Disk { get; set; }
    public string OS { get; set; }
}

PS don't need any classes, if you add one more dictionary

var servers = System.Text.Json.JsonSerializer
.Deserialize<Dictionary<string, Dictionary<string, Dictionary<string, string>>[]>>(json);

    foreach (var server in servers)
    {
        Console.WriteLine(server.Key);
        foreach (var os in server.Value)
        {
            foreach (var entry in os)
            {
                Console.WriteLine(entry.Key);

                Console.WriteLine(entry.Value["Price"]);
                Console.WriteLine(entry.Value["Cores"]);
                //....
            }
        }
    }
  • Related