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.
Related
I am executing a stored procedure on my server which returns a DataTable. The DataTable has some columns that have JSON data in them. When I return the result to the client the top-level of the DataTable is properly formatted to JSON but the columns with JSON data are returned as strings. How can I convert the entire table (including columns with JSON) to JSON before returning to the client?
DataTable
ColA ColB ColC
1 Test [{"ColD":2,"ColE":"Another Test"}]
What I'm Getting
[
{
"ColA": 1,
"ColB": "Test",
"ColC": "[{\"ColD\":2,\"ColE\":\"Another Test\"}]"
}
]
What I Need
[
{
"ColA": 1,
"ColB": "Test",
"ColC": [
{
"ColD": 2,
"ColE": "Another Test"
}
]
}
]
I had a breakthrough after posting the question. I created an extension method for the DataTable that would convert the DataTable to a List<Dictionary<string, object>>. In the process I check for values that start with [ or { and deserialize them using JsonConvert.DeserializeObject.
public static List<Dictionary<string, object>> ToJson(this DataTable dt)
{
var list = new List<Dictionary<string, object>>();
foreach (DataRow row in dt.Rows)
{
var dict = new Dictionary<string, object>();
foreach (DataColumn col in dt.Columns)
{
if (row[col].ToString().StartsWith('{') || row[col].ToString().StartsWith('['))
{
dict[col.ColumnName] = JsonConvert.DeserializeObject(row[col].ToString());
}
else
{
dict[col.ColumnName] = row[col];
}
}
list.Add(dict);
}
return list;
}
I am trying to export a number of datasets to Excel in an Angular 6 application. For that I am using XLSX and File-save as given in this ex:
https://medium.com/#madhavmahesh/exporting-an-excel-file-in-angular-927756ac9857
The problem is that the fields might keep changing time to time, so I need somthing dynamic (do not want to specify column names). For that I found a very good example:
Binding Json data to a table in mvc 4
However, I am not getting the data in the right format. I need something like array of array.
I am assuming the return type should be async Task<JsonResult> in that case but not sure how to make it work.
I am attaching two images - of the result I am getting
and the intended result
Here is code from the sample cited. The stored proc call to GetMyData, uses SqlAdapter and there is no need to specify field names
public JsonResult GetValue()
{
JsonResult json = new JsonResult();
DataSet ds = GetMyData();
/*LoadDoctordetailsNew is method where i get data from database and convert
to dataset.It returns a dataset*/
string returnData = GetJson(ds.Tables[0]);
json.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
json.Data = returnData;
return json;
}
public static string GetJson(DataTable dt)
{
System.Web.Script.Serialization.JavaScriptSerializer serializer =
new System.Web.Script.Serialization.JavaScriptSerializer();
List<Dictionary<string, object>> rows =
new List<Dictionary<string, object>>();
Dictionary<string, object> row = null;
foreach (DataRow dr in dt.Rows)
{
row = new Dictionary<string, object>();
foreach (DataColumn col in dt.Columns)
{
row.Add(col.ColumnName, dr[col]);
}
rows.Add(row);
}
return serializer.Serialize(rows);
}
public static DataSet GetMyData()
{
try
{
using (SqlConnection connection = Connection.GetConnection())
{
SqlDataAdapter da = new SqlDataAdapter("dbo.MySQLStoredproc", connection);
da.SelectCommand.CommandType = CommandType.StoredProcedure;
DataSet ds = new DataSet();
da.Fill(ds);
return ds;
}
}
catch (Exception ex)
{
throw;
}
}
Please guide!
P.S.
This technique is using Dapper. It returns data as desired (Array of Array) format, but in the Object we have to specify column names which will be hard coding and therefore, I can't use
public static IEnumerable<Object> GetMyData()
{
var strQuery = #"[dbo].[Myproc]";
IEnumerable< Object > items = new List<Object>(0);
var p = new DynamicParameters();
using (SqlConnection con = Connection.GetConnection())
{
items = con.Query<Object>(strQuery, param: p, commandTimeout: 120, commandType: System.Data.CommandType.StoredProcedure);
}
return items;
}
Call from MVC Controller
[HttpPost]
public async Task<JsonResult> SelectMyData()
{
var task = Task.Run(() => Request.GetMyData());
var retData = await task;
return new JsonResult
{
ContentType = "application/json",
Data = retData,
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
MaxJsonLength = int.MaxValue
};
}
You should return the List<Dictionary<string, object>> instead of string. You don't need to Serialize the data it will be take care by JsonResult
public JsonResult GetValue()
{
JsonResult json = new JsonResult();
DataSet ds = GetMyData();
/*LoadDoctordetailsNew is method where i get data from database and convert
to dataset.It returns a dataset*/
json.Data = GetJson(ds.Tables[0]);
json.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
return json;
}
public static List<Dictionary<string, object>> GetJson(DataTable dt)
{
List<Dictionary<string, object>> rows =
new List<Dictionary<string, object>>();
Dictionary<string, object> row = null;
foreach (DataRow dr in dt.Rows)
{
row = new Dictionary<string, object>();
foreach (DataColumn col in dt.Columns)
{
row.Add(col.ColumnName, dr[col]);
}
rows.Add(row);
}
return rows;
}
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.
I am new to C# and gone through lot of questions in Stackoverflow.com and didn't find the solution for my requirement. So finally posting here.
My requirement is to create the dynamic properties from datatable column names and set the values to dynamic properties from datatable. and finally bind the data to gridview.
So I decided to follow below steps to achieve this functionality( kindly Correct me If I am wrong)
my datatable contains 26 rows and 10 columns of data
Create a Class A
Add dynamic properties to A from datatable(column names)
Set values to properties of A
Make class A to List of A
Bind List of A to GridView
I have done the below steps
1.
[Serializable]
public class A
{
public A()
{
}
}
2 & 3.
DataTable dt = getData();
dynamic expando = new ExpandoObject();
foreach (DataRow row in dt.Rows)
{
foreach (DataColumn col in dt.Columns)
{
var expandoDict = expando as IDictionary<String, Object>;
if (expandoDict.ContainsKey(col.ToString()))
expandoDict[col.ToString()] = row[col.ColumnName].ToString();
else
expandoDict.Add(col.ToString(), row[col.ColumnName].ToString());
}
}
After executing the above for loop, "expando" object contains only last row of datatable.
Can you please help me how to fix the steps 2 to 5.
From what I understand, this code may be more what you are looking for. This should get the data into the expandoList for you. You will then need to handle the binding to the GridView.
DataTable dt = getData();
List<dynamic> expandoList = new List<dynamic>();
foreach (DataRow row in dt.Rows)
{
//create a new ExpandoObject() at each row
var expandoDict = new ExpandoObject() as IDictionary<String, Object>;
foreach (DataColumn col in dt.Columns)
{
//put every column of this row into the new dictionary
expandoDict.Add(col.ToString(), row[col.ColumnName].ToString());
}
//add this "row" to the list
expandoList.Add(expandoDict);
}
Here's an extension method that would convert your datatable to list of Dynamic objects:
public static class DataTableExtension
{
public static IEnumerable<dynamic> AsDynamicEnumerable(this DataTable table)
{
// Validate argument here..
return table.AsEnumerable().Select(row => new DynamicRow(row));
}
private sealed class DynamicRow : DynamicObject
{
private readonly DataRow _row;
internal DynamicRow(DataRow row) { _row = row; }
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
var retVal = _row.Table.Columns.Contains(binder.Name);
result = retVal ? _row[binder.Name] : null;
return retVal;
}
}
}
Usage: IEnumerable<dynamic> result = getData().AsEnumerable();
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);
}