Changing Dictionary Key - c#

I am getting data from data table and convert it into json like this:
public object DataTableToJSON(DataTable table)
{
var list = new List<Dictionary<string, object>>();
foreach (DataRow row in table.Rows)
{
var dict = new Dictionary<string, object>();
foreach (DataColumn col in table.Columns)
{
dict.Add(col.ColumnName,row[col]);
}
list.Add(dict);
}
JavaScriptSerializer serializer = new JavaScriptSerializer();
return serializer.Serialize(list);
}
But while iterating through JSON data , this method is giving key names as column1,column2...(as datatable don't have any column name)
I want the column names should be something like 1,2...
How can I achieve this using above method ?

Change
dict.Add(col.ColumnName,row[col]);
to
var keyName = string.IsNullOrEmpty(col.ColumnName)
? col.Ordinal + 1
: col.ColumnName;
dict.Add(keyName, row[col]);
When you have a column name this will be taken and we you don't have one you will take the index + 1 of the column.

You can build in a Counter
public object DataTableToJSON(DataTable table)
{
var list = new List<Dictionary<string, object>>();
foreach (DataRow row in table.Rows)
{
var dict = new Dictionary<string, object>();
var counter = 1;
foreach (DataColumn col in table.Columns)
{
dict.Add(counter.ToString(),row[col]);
counter++;
}
list.Add(dict);
}
JavaScriptSerializer serializer = new JavaScriptSerializer();
return serializer.Serialize(list);
}
But keep in mind: double keynames are not allowed.

The Ordinal property of the DataColumn object will give you the position of the column, so you can tweak your code to use this.
public object DataTableToJSON(DataTable table)
{
var list = new List<Dictionary<string, object>>();
foreach (DataRow row in table.Rows)
{
var dict = new Dictionary<string, object>();
foreach (DataColumn col in table.Columns)
{
dict.Add((col.Ordinal+1).ToString(),row[col]) ;
}
list.Add(dict);
}
JavaScriptSerializer serializer = new JavaScriptSerializer();
return serializer.Serialize(list);
}

Related

How to convert two table data in json formate

I want JSON data in this format. And itemlist data is coming from itemlist table and remaining are from another table .itemlist is the 2nd table name.
JSON
{
\"supplyType\":\"O\",
\"subSupplyType\":\"1\",
\"subSupplyDesc\":\"\",
\"docType\":\"INV\",
\"docNo\":\"107500F18TO0045\",
\"docDate\":\"15/10/2017\",
\"fromGstin\":\"03EHFPS5910D3A1\",
\"fromTrdName\":\"Diwa\",
\"fromAddr1\":\"2ND CROSS NO 59 19 \",
\"fromAddr2\":\"GROUND FLOOR OSBORNE ROAD \",
\"fromPlace\":\"BANGALORE\",
\"fromPincode\":560042,
\"actFromStateCode\":29,
\"fromStateCode\":29,
\"toGstin\":\"02EHFPS10D2Z0\",
\"toTrdName\":\"sthuthya\",
\"toAddr1\":\"Shree Nilaya\",
\"toAddr2\":\"Dasarahosahalli\",
\"toPlace\":\"Beml Nagar\",
\"toPincode\":400013,
\"actToStateCode\":9,
\"toStateCode\":27,
\"transactionType\":4,
\"dispatchFromGSTIN\":\"29AAAAA1303P1ZV\",
\"dispatchFromTradeName\":\"xyz Traders\",
\"shipToGSTIN\":\"03EHFPS5910D3A1\",
\"shipToTradeName\":\"XYZ Traders\",
\"otherValue\":-100,
\"totalValue\":100,
\"cgstValue\":0,
\"sgstValue\":0,
\"igstValue\":300.67,
\"cessValue\":400.56,
\"cessNonAdvolValue\":400,
\"totInvValue\":68358,
\"transporterId\":\"\",
\"transporterName\":\"\",
\"transDocNo\":\"\",
\"transMode\":\"1\",
\"transDistance\":\"656\",
\"transDocDate\":\"\",
\"vehicleNo\":\"PVC1234\",
\"vehicleType\":\"R\",
\"itemList\":[
{
\"productName\":\"rice\",
\"productDesc\":\"Wheat\",
\"hsnCode\":1001,
\"quantity\":4,
\"qtyUnit\":\"BOX\",
\"cgstRate\":0,
\"sgstRate\":0,
\"igstRate\":3,
\"cessRate\":0,
\"cessNonAdvol\":0,
\"taxableAmount\":56099
}
]
}";
//
Dictionary<string, object> rows = new Dictionary<string, object>();
Dictionary<string, object> rowelement;
[System.Web.Http.HttpGet]
public JsonResult Show()
{
JavaScriptSerializer serial1 = new JavaScriptSerializer();
Registration obj = new Registration();
DataTable dt = new DataTable();
dt = obj.employeedetails();
if (dt.Rows.Count > 0)
{
foreach (DataRow dr in dt.Rows)
{
rowelement = new Dictionary<string, object>();
foreach (DataColumn col in dt.Columns)
{
rowelement.Add(col.ColumnName, dr[col]);
}
rows.Add("",rowelement);
}
}
return Json(rows, JsonRequestBehavior.AllowGet);
This is just an approach. not a complete solution.
You can create a new class, fill the data coming from DB in it, serialize it using JSON library.

Convert DataTable into list when no of column is dynamic

I have a datatable in which no of columns is dynamic. I need a list with header name and value.I found a question similar to this question.
enter link description here
But can not getting desired output.
Output with this solution
In Dynamic View :
In Result View
I m using this Code for Convert to dynamic object :
public static List<dynamic> ToDynamic(this DataTable dt)
{
var dynamicDt = new List<dynamic>();
foreach (DataRow row in dt.Rows)
{
dynamic dyn = new ExpandoObject();
foreach (DataColumn column in dt.Columns)
{
var dic = (IDictionary<string, object>)dyn;
dic[column.ColumnName] = row[column];
}
dynamicDt.Add(dyn);
}
return dynamicDt;
}
Need a output like that :-
How can i achieve this?
You can achieve that by modifying the ToDynamic method you are using. The original method is:
public static class DataTableExtensions
{
public static List<dynamic> ToDynamic(this DataTable dt)
{
var dynamicDt = new List<dynamic>();
foreach (DataRow row in dt.Rows)
{
dynamic dyn = new ExpandoObject();
dynamicDt.Add(dyn);
//--------- change from here
foreach (DataColumn column in dt.Columns)
{
var dic = (IDictionary<string, object>)dyn;
dic[column.ColumnName] = row[column];
}
//--------- change up to here
}
return dynamicDt;
}
}
Replace the lines between the "change" comments into:
foreach (var columnName in new[] {"A", "B", "C", "D", "E"} )
{
var dic = (IDictionary<string, object>)dyn;
if(dt.Columns.Contains(columnName))
dic[columnName] = row[dt.Columns[columnName]];
else
dic[columnName] = 0;
}
That's assuming you need column names A to E, adjust as appropriate if you need more columns.

C# KeyValue foreach column in row

I am here today trying to work out how I can do this. I have the code below to look through each column in a DataRow, but how can I access the key AND value? I want to assign it to a dictionary in the class but I can't seem to get both of them, the only way I can get anything is by calling:
var columnValue = playerDataRow[column];
Here is the full thing:
using (var mysqlConnection = Sirius.GetServer().GetDatabaseManager().GetConnection())
{
mysqlConnection.SetQuery("SELECT * FROM `users` WHERE `auth_ticket` = #authTicket LIMIT 1");
mysqlConnection.AddParameter("authTicket", authTicket);
var playerDataTable = mysqlConnection.GetTable();
foreach (DataRow playerDataRow in playerDataTable.Rows)
{
foreach (DataColumn column in playerDataTable.Columns)
{
var columnValue = playerDataRow[column];
}
}
}
foreach (DataRow playerDataRow in playerDataTable.Rows)
{
var myDic = new Dictionary<string, object>();
foreach (DataColumn column in playerDataTable.Columns)
{
myDic.Add(column.ColumnName, playerDataRow[column]);
}
}
the variable column will be the key and the value will be columnValue
looks that you only want one row of output - perhaps for this specific user based on auth_ticket
here is an example of how to get all values for this row into a Dictionary of strings (I'm converting all data to strings by the way just for this example)
var htRowValues = new Dictionary<string,string>();
using (var mysqlConnection = Sirius.GetServer().GetDatabaseManager().GetConnection())
{
mysqlConnection.SetQuery("SELECT * FROM `users` WHERE `auth_ticket` = #authTicket LIMIT 1");
mysqlConnection.AddParameter("authTicket", authTicket);
var playerDataTable = mysqlConnection.GetTable();
foreach (DataRow playerDataRow in playerDataTable.Rows)
{
foreach (DataColumn column in playerDataTable.Columns)
{
var columnValue = playerDataRow[column];
htRowValues[column.ColumnName]=System.Convert.ToString(columnValue);
}
}
}
now you have all column values in the dictionary for this one row of data.

Convert dynamic list to datatable c#

am searching and cracking my brain on how to convert a dynamic list to a databale,
c#, please advise, thanks
List<dynamic>dlist=new List<dynamic>
to
DataTable
I think you looking something like this. Hope it's working for you.
From dynamic list to DataTable:
List<dynamic> dlist=new List<dynamic>
var json = JsonConvert.SerializeObject(dlist);
DataTable dataTable = (DataTable)JsonConvert.DeserializeObject(json, (typeof(DataTable)));
Also to get JsonString from DataTable:
string JSONresult = JsonConvert.SerializeObject(dataTable);
The following is the method through which you can convert any list object to datatable..
public DataTable ConvertToDataTable<T>(IList<T> data)
{
PropertyDescriptorCollection properties =
TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
foreach (PropertyDescriptor prop in properties)
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
foreach (T item in data)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in properties)
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
table.Rows.Add(row);
}
return table;
}
http://social.msdn.microsoft.com/Forums/vstudio/en-US/6ffcb247-77fb-40b4-bcba-08ba377ab9db/converting-a-list-to-datatable?forum=csharpgeneral
public DataTable ToDataTable<T>(dynamic items)
{
DataTable dtDataTable = new DataTable();
if (items.Count == 0) return dtDataTable;
((IEnumerable)items[0]).Cast<dynamic>().Select(p => p.Name).ToList().ForEach(col => { dtDataTable.Columns.Add(col); });
((IEnumerable)items).Cast<dynamic>().ToList().
ForEach(data =>
{
DataRow dr = dtDataTable.NewRow();
((IEnumerable)data).Cast<dynamic>().ToList().ForEach(Col => { dr[Col.Name] = Col.Value; });
dtDataTable.Rows.Add(dr);
});
return dtDataTable;
}
I don't know why you need this, however, you can use this ObjectShredder using reflection which can convert anything to DataTable, so even dynamic or anonymous types:
Implement CopyToDataTable<T> Where the generic Type T Is Not a DataRow
However, my suggestion is to not name that extension method CopyToDataTable but for example CopyAnyToDataTable to avoid conflicts with the existing extension method CopyToDataTable.
Use this function ,
public static DataTable ConvertToDatatable<T>(this IList<T> data)
{
PropertyDescriptorCollection props =
TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
for(int i = 0 ; i < props.Count ; i++)
{
PropertyDescriptor prop = props[i];
table.Columns.Add(prop.Name, prop.PropertyType);
}
object[] values = new object[props.Count];
foreach (T item in data)
{
for (int i = 0; i < values.Length; i++)
{
values[i] = props[i].GetValue(item);
}
table.Rows.Add(values);
}
return table;
}
If the underlying type is ExpandoObject, then you need to check for IDictionary instead of going via reflection. Hopefully this helps someone else in the future:
public static DataTable ConvertToDataTable<T>(IEnumerable<T> data)
{
DataTable table = new DataTable();
foreach (T item in data)
{
if (item is IDictionary<string, object> dict)
{
foreach (var key in dict)
{
table.Columns.Add(key.Key, key.Value?.GetType() ?? typeof(object));
}
break;
}
foreach (var prop in typeof(T).GetProperties())
{
table.Columns.Add(prop.Name, prop.PropertyType);
}
break;
}
DataRow row = null;
foreach (T item in data)
{
if (item is IDictionary<string, object> dict)
{
row = table.NewRow();
foreach (var key in dict)
{
row[key.Key] = key.Value;
}
table.Rows.Add(row);
continue;
}
row = table.NewRow();
foreach (var prop in typeof(T).GetProperties())
{
row[prop.Name] = prop.GetValue(item);
}
table.Rows.Add(row);
}
return table;
}
To Convert the Dynamic List object into DataTable using C#
public DataTable DynamicToDT(List<object> objects)
{
DataTable dt = new DataTable("StudyRecords"); // Runtime Datatable
string[] arr = { "Name", "Department", "CollegeName", "Address" };// Column Name for DataTable
if (objects != null && objects.Count > 0)
{
for (int i = 0; i < objects.Count; i++)
{
dt.Columns.Add(arr[i]);
if (i == 0)
{
var items = objects[0] as IEnumerable<string>;
foreach (var itm in items)
{
DataRow dr1 = dt.NewRow(); // Adding values to Datatable
dr1[arr[i]] = itm;
dt.Rows.Add(dr1);
}
}
else
{
var items = objects[i] as IEnumerable<string>;
int count = 0;
foreach (var itm in items)
{
dt.Rows[count][arr[i]] = itm;
count++;
}
}
}
return dt; // Converted Dynamic list to Datatable
}
return null;
}
public static DataTable DynamicToDT(List objects)
{
var data = objects.ToArray();
if (data.Count() == 0) return null;
var dt = new DataTable();
foreach (var key in ((IDictionary<string, object>)data[0]).Keys)
{
dt.Columns.Add(key);
}
foreach (var d in data)
{
dt.Rows.Add(((IDictionary<string, object>)d).Values.ToArray());
}
return dt;
}
// Obtem a lista dinamica via chamada API
List<dynamic> resultado = ExecutaQuery(sql);
// converte a lista dinamica com o resultado em JSON
string json = JsonConvert.SerializeObject(resultado);
// converte o json em datatable
DataTable dataTable = (DataTable)JsonConvert.DeserializeObject(json, (typeof(DataTable)));

Coverting List of Dictionary to DataTable

Currently we are doing this by looping through each value of list and dictionary:
private DataTable ChangeToDictionary(List<Dictionary<string,int>> list)
{
DataTable datatTableReturn = new DataTable();
if (list.Count() > 0)
{
Dictionary<string, int> haeders = list.ElementAt(0);
foreach (var colHead in haeders)
{
datatTableReturn.Columns.Add(colHead.Key);
}
}
foreach (var row in list)
{
DataRow dataRow = datatTableReturn.NewRow();
foreach (var col in row)
{
dataRow[col.Key] = col.Value;
}
datatTableReturn.Rows.Add(dataRow);
}
return datatTableReturn;
}
But is there a better way? Looping through so many times doesn't feel good
The answers above don't address the issue of the dictionary having more than 1 row. This solution addresses the issue.
static DataTable ToDataTable(List<Dictionary<string, int>> list)
{
DataTable result = new DataTable();
if (list.Count == 0)
return result;
var columnNames = list.SelectMany(dict=>dict.Keys).Distinct();
result.Columns.AddRange(columnNames.Select(c=>new DataColumn(c)).ToArray());
foreach (Dictionary<string,int> item in list)
{
var row = result.NewRow();
foreach (var key in item.Keys)
{
row[key] = item[key];
}
result.Rows.Add(row);
}
return result;
}
static void Main(string[] args)
{
List<Dictionary<string, int>> it = new List<Dictionary<string, int>>();
Dictionary<string, int> dict = new Dictionary<string, int>();
dict.Add("a", 1);
dict.Add("b", 2);
dict.Add("c", 3);
it.Add(dict);
dict = new Dictionary<string, int>();
dict.Add("bob", 34);
dict.Add("tom", 37);
it.Add(dict);
dict = new Dictionary<string, int>();
dict.Add("Yip Yip", 8);
dict.Add("Yap Yap", 9);
it.Add(dict);
DataTable table = ToDictionary(it);
foreach (DataColumn col in table.Columns)
Console.Write("{0}\t", col.ColumnName);
Console.WriteLine();
foreach (DataRow row in table.Rows)
{
foreach (DataColumn column in table.Columns)
Console.Write("{0}\t", row[column].ToString());
Console.WriteLine();
}
Console.ReadLine();
}
And the output looks like...
a b c bob tom Yip Yip Yap Yap
1 2 3
34 37
8 9
Speed, elegance and reusability don't go together. You always choose more important one, and try to balance other two.
Faster the code, uglier it is.
Prettier it is, less reusable it is.
Here's an example of "elegant" solution, but that goes with it not being very readable.
private static DataTable ToDictionary(List<Dictionary<string, int>> list)
{
DataTable result = new DataTable();
if (list.Count == 0)
return result;
result.Columns.AddRange(
list.First().Select(r => new DataColumn(r.Key)).ToArray()
);
list.ForEach(r => result.Rows.Add(r.Select(c => c.Value).Cast<object>().ToArray()));
return result;
}
Try this
List<Dictionary<string, object>> ListDic;
var stringListDic = JsonConvert.SerializeObject(ListDic);
var dataTable = JsonConvert.DeserializeObject<DataTable>(stringListDic);
Try this:
private DataTable GetDataTableFromDictionaries<T>(List<Dictionary<string, T>> list)
{
DataTable dataTable = new DataTable();
if (list == null || !list.Any()) return dataTable;
foreach (var column in list.First().Select(c => new DataColumn(c.Key, typeof(T))))
{
dataTable.Columns.Add(column);
}
foreach (var row in list.Select(
r =>
{
var dataRow = dataTable.NewRow();
r.ToList().ForEach(c => dataRow.SetField(c.Key, c.Value));
return dataRow;
}))
{
dataTable.Rows.Add(row);
}
return dataTable;
}
How about something like the code below?
Good, because it iterates each row exactly once. It should be pretty quick, I've included obvious exceptions to make the code safer.
private static DataTable DictionariesToDataTable<T>(
IEnumerable<IDictionary<string, T>> source)
{
if (source == null)
{
return null;
}
var result = new DataTable();
using (var e = source.GetEnumerator())
{
if (!e.MoveNext())
{
return result;
}
if (e.Current.Keys.Length == 0)
{
throw new InvalidOperationException();
}
var length = e.Current.Keys.Length;
result.Columns.AddRange(
e.Current.Keys.Select(k => new DataColumn(k, typeof(T))).ToArray());
do
{
if (e.Current.Values.Length != length)
{
throw new InvalidOperationException();
}
result.Rows.Add(e.Current.Values);
}
while (e.MoveNext());
return result;
}
}
try my solution, seems very clean to me:
private DataTable DictonarysToDataTable(List<Dictionary<string, int>> list)
{
DataTable table = new DataTable();
foreach (Dictionary<string,string> dict in list) //for every dictonary in the list ..
{
foreach (KeyValuePair<string,int> entry in dict) //for every entry in every dict
{
if (!myTable.Columns.Contains(entry.Key.ToString()))//if it doesn't exist yet
{
myTable.Columns.Add(entry.Key); //add all it's keys as columns to the table
}
}
table.Rows.Add(dict.Values.ToArray()); //add the the Values of every dict in the list as a new row
}
return table;
}
Edit:
Oh Snap, this works only for one Dictionary .. i didn't think it through.
But maybie you can modify it to work for a List of Dictionarys ..
Give this a try please
DataTable table = new DataTable();
foreach (IDictionary<string, object> row in DeviceTypeReport)
{
foreach (KeyValuePair<string, object> entry in row)
{
if (!table.Columns.Contains(entry.Key.ToString()))
{
table.Columns.Add(entry.Key);
}
}
table.Rows.Add(row.Values.ToArray());
}
private DataTable toDataTable(List<RetirementDiskModelDto> retirementDiskModelDtos)
{
DataTable result = new DataTable();
foreach (var col in retirementDiskModelDtos.FirstOrDefault().Items)
result.Columns.Add(col.Key);
foreach (var row in retirementDiskModelDtos)
{
DataRow newrow = result.NewRow();
foreach (var col in retirementDiskModelDtos.FirstOrDefault().Items)
newrow[col.Key] = col.Value;
result.Rows.Add(newrow);
}
return result;
}

Categories

Resources