Home > Back-end >  DataTable to complex nested JSON
DataTable to complex nested JSON

Time:12-31

I have a SQL Query into a DataTable that I would like to convert into a nested json document. I tried to use nested dictionaries but I don't think I created enough nests and I'm wondering if that's really the best approach. I also tried dynamic parameters but wanted to take a step back and ask if I'm doing this correctly; I'm fairly new to C#. Another issue is the request for "header information" that they would like to appear at the top of the JSON; this information isn't in the DataTable as it's currently manually entered information into a config file variable

below is an example of the data table

database table tablesize column datatype
marketing contacts 535MB contactid int
marketing contacts 535MB contact_firstname varchar(50)
marketing contacts 535MB contact_lastname varchar(50)
marketing addresses 1200MB addressid int
marketing addresses 1200MB address1 varchar(100)
HR employees 600MB employeeID int
HR employees 600MB employee_firstname varchar(50)

below is the expected JSON structure

 REQUESTED_BY: bob smith
 REQUEST_DATE: 12/30/2022  08:30
 COMPLETED_BY: jane doe
 COMPLETED_ON: 12/30/2022  08:55
      Databases:
            marketing
                     tables:
                          contacts
                          tablesize:535MB
                               columns:
                                    contactid
                                         datatype: int
                                    contact_firstname
                                         datatype: varchar(50)
                                    contact_lastname
                                         datatype: varchar(50)
                          addresses
                          tablesize:1200MB
                               columns:
                                    addressid
                                         datatype: int
                                    address1
                                         datatype: varchar(100)
            HR
                     tables:
                          employees
                          tablesize:600MB
                               columns:
                                    employeeid
                                         datatype: int
                                    employee_firstname
                                         datatype: varchar(50)

here's a code snippet. I tried to start small and work my way out of the nest

        var tbls = new Dictionary<string, Dictionary<string,string>>();

        foreach (DataRow row in dbrequestdt.Rows)
        {
            string table = row["table"].ToString();
            Dictionary<string, string> columns;

            if(!tbls.TryGetValue(table, out columns))
            {
                columns = new Dictionary<string, string>();
                tbls.Add(table, columns);
            }
            columns.Add(row["column"].ToString(), row["datatype"].ToString());
        }

CodePudding user response:

I have generated JSON based on your text table for testing purposes.

string jsonBasedOnTable = "[{\"database\":\"marketing\",\"table\":\"contacts\",\"tablesize\":\"535MB\",\"column\":\"contactid\",\"datatype\":\"int\"},{\"database\":\"marketing\",\"table\":\"contacts\",\"tablesize\":\"535MB\",\"column\":\"contact_firstname\",\"datatype\":\"varchar(50)\"},{\"database\":\"marketing\",\"table\":\"contacts\",\"tablesize\":\"535MB\",\"column\":\"contact_lastname\",\"datatype\":\"varchar(50)\"},{\"database\":\"marketing\",\"table\":\"addresses\",\"tablesize\":\"1200MB\",\"column\":\"addressid\",\"datatype\":\"int\"},{\"database\":\"marketing\",\"table\":\"addresses\",\"tablesize\":\"1200MB\",\"column\":\"address1\",\"datatype\":\"varchar(100)\"},{\"database\":\"HR\",\"table\":\"employees\",\"tablesize\":\"600MB\",\"column\":\"employeeID\",\"datatype\":\"int\"},{\"database\":\"HR\",\"table\":\"employees\",\"tablesize\":\"600MB\",\"column\":\"employee_firstname\",\"datatype\":\"varchar(50)\"}]";

According to your table structure implemented the model classes as,

public class DatabaseInfo
{
    public string database { get; set; }
    public TableInfo[] tables { get; set; }
}

public class TableInfo
{
    public string table { get; set; }
    public string tablesize { get; set; }
    public ColumnInfo[] columns { get; set; }
}

public class ColumnInfo
{
    public string column { get; set; }
    public string datatype { get; set; }
}

Then you can do something like this.

DataTable dataTable = (DataTable)JsonConvert.DeserializeObject(jsonBasedOnTable, (typeof(DataTable)));

List < DatabaseInfo > databases = new List < DatabaseInfo > ();
foreach(DataRow row in dataTable.Rows) {
  string database = row["database"].ToString();
  string table = row["table"].ToString();
  string tablesize = row["tablesize"].ToString();
  string column = row["column"].ToString();
  string datatype = row["datatype"].ToString();

  // here I'm cheking same record is avialble
  DatabaseInfo databaseInfo = databases.FirstOrDefault(d => d.database == database);
  if (databaseInfo == null) {
    databaseInfo = new DatabaseInfo {
      database = database,
        tables = new TableInfo[0]
    };
    databases.Add(databaseInfo);
  }

  TableInfo tableInfo = databaseInfo.tables.FirstOrDefault(t => t.table == table);
  if (tableInfo == null) {
    tableInfo = new TableInfo {
      table = table,
        tablesize = tablesize,
        columns = new ColumnInfo[0]
    };
    databaseInfo.tables = databaseInfo.tables.Concat(new TableInfo[] {
      tableInfo
    }).ToArray();
  }

  tableInfo.columns = tableInfo.columns.Concat(new ColumnInfo[] {
    new ColumnInfo {
      column = column, datatype = datatype
    }
  }).ToArray();
}

string jsons = JsonConvert.SerializeObject(databases);

Working fiddle https://dotnetfiddle.net/yAzh71

  • Related