- Quiero obtener registros de la base de datos en un archivo
DataTable
. - Luego convierta el
DataTable
en un objeto JSON. - Devuelve el objeto JSON a mi función JavaScript.
Utilizo este código llamando a:
string result = JsonConvert.SerializeObject(DatatableToDictionary(queryResult, "Title"), Newtonsoft.Json.Formatting.Indented);
Para convertir un DataTable a JSON, funciona correctamente y devuelve lo siguiente:
{
"1": {
"viewCount": 703,
"clickCount": 98
},
"2": {
"viewCount": 509,
"clickCount": 85
},
"3": {
"viewCount": 578,
"clickCount": 86
},
"4": {
"viewCount": 737,
"clickCount": 108
},
"5": {
"viewCount": 769,
"clickCount": 130
}
}
Pero me gustaría que devolviera lo siguiente:
{"records":[
{
"Title": 1,
"viewCount": 703,
"clickCount": 98
},
{
"Title": 2,
"viewCount": 509,
"clickCount": 85
},
{
"Title": 3,
"viewCount": 578,
"clickCount": 86
},
{
"Title": 4,
"viewCount": 737,
"clickCount": 108
},
{
"Title": 5,
"viewCount": 769,
"clickCount": 130
}
]}
¿Cómo puedo hacer esto?
Respuestas:
Este fragmento de código de Convert Datatable to JSON String en C #, VB.NET podría ayudarlo. Utiliza System.Web.Script.Serialization.JavaScriptSerializer para serializar el contenido en formato JSON:
public string ConvertDataTabletoString() { DataTable dt = new DataTable(); using (SqlConnection con = new SqlConnection("Data Source=SureshDasari;Initial Catalog=master;Integrated Security=true")) { using (SqlCommand cmd = new SqlCommand("select title=City,lat=latitude,lng=longitude,description from LocationDetails", con)) { con.Open(); SqlDataAdapter da = new SqlDataAdapter(cmd); da.Fill(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; 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); } } }
fuente
Podemos realizar la tarea de dos formas simples, una usando Json.NET dll y otra usando la clase StringBuilder.
Usando Newtonsoft Json.NET
string JSONresult; JSONresult = JsonConvert.SerializeObject(dt); Response.Write(JSONresult);
Enlace de referencia: Newtonsoft: Convertir DataTable a objeto JSON en ASP.Net C #
Usando StringBuilder
public string DataTableToJsonObj(DataTable dt) { DataSet ds = new DataSet(); ds.Merge(dt); StringBuilder JsonString = new StringBuilder(); if (ds != null && ds.Tables[0].Rows.Count > 0) { JsonString.Append("["); for (int i = 0; i < ds.Tables[0].Rows.Count; i++) { JsonString.Append("{"); for (int j = 0; j < ds.Tables[0].Columns.Count; j++) { if (j < ds.Tables[0].Columns.Count - 1) { JsonString.Append("\"" + ds.Tables[0].Columns[j].ColumnName.ToString() + "\":" + "\"" + ds.Tables[0].Rows[i][j].ToString() + "\","); } else if (j == ds.Tables[0].Columns.Count - 1) { JsonString.Append("\"" + ds.Tables[0].Columns[j].ColumnName.ToString() + "\":" + "\"" + ds.Tables[0].Rows[i][j].ToString() + "\""); } } if (i == ds.Tables[0].Rows.Count - 1) { JsonString.Append("}"); } else { JsonString.Append("},"); } } JsonString.Append("]"); return JsonString.ToString(); } else { return null; } }
fuente
Esto tiene un enfoque similar a la respuesta aceptada, pero usa LINQ para convertir la tabla de datos en una lista en una sola línea de código.
//convert datatable to list using LINQ. Input datatable is "dt", returning list of "name:value" tuples var lst = dt.AsEnumerable() .Select(r => r.Table.Columns.Cast<DataColumn>() .Select(c => new KeyValuePair<string, object>(c.ColumnName, r[c.Ordinal]) ).ToDictionary(z=>z.Key,z=>z.Value) ).ToList(); //now serialize it var serializer = new System.Web.Script.Serialization.JavaScriptSerializer(); return serializer.Serialize(lst);
Esta es una forma increíblemente útil de enumerar una tabla de datos, que normalmente requeriría un montón de codificación. Aquí hay algunas variaciones:
//convert to list with array of values for each row var list1 = dt.AsEnumerable().Select(r => r.ItemArray.ToList()).ToList(); //convert to list of first column values only var list2 = dt.AsEnumerable().Select(r => r.ItemArray[0]).ToList(); // parse a datatable with conditions and get CSV string string MalesOver21 = string.Join(",", dt.AsEnumerable() .Where(r => r["GENDER"].ToString()=="M" && r.Field<int>("AGE")>21) .Select(r => r.Field<string>("FULLNAME")) );
Esto está fuera del tema de la pregunta original, pero en aras de la integridad, mencionaría que si solo desea filtrar filas de una tabla de datos existente, consulte esta respuesta
fuente
Una forma alternativa sin usar el serializador de JavaScript:
public static string DataTableToJSON(DataTable Dt) { string[] StrDc = new string[Dt.Columns.Count]; string HeadStr = string.Empty; for (int i = 0; i < Dt.Columns.Count; i++) { StrDc[i] = Dt.Columns[i].Caption; HeadStr += "\"" + StrDc[i] + "\":\"" + StrDc[i] + i.ToString() + "¾" + "\","; } HeadStr = HeadStr.Substring(0, HeadStr.Length - 1); StringBuilder Sb = new StringBuilder(); Sb.Append("["); for (int i = 0; i < Dt.Rows.Count; i++) { string TempStr = HeadStr; for (int j = 0; j < Dt.Columns.Count; j++) { TempStr = TempStr.Replace(Dt.Columns[j] + j.ToString() + "¾", Dt.Rows[i][j].ToString().Trim()); } //Sb.AppendFormat("{{{0}}},",TempStr); Sb.Append("{"+TempStr + "},"); } Sb = new StringBuilder(Sb.ToString().Substring(0, Sb.ToString().Length - 1)); if(Sb.ToString().Length>0) Sb.Append("]"); return StripControlChars(Sb.ToString()); } //To strip control characters: //A character that does not represent a printable character but //serves to initiate a particular action. public static string StripControlChars(string s) { return Regex.Replace(s, @"[^\x20-\x7F]", ""); }
fuente
Puede usar la misma forma que especificó Alireza Maddah y si desea usar dos tablas de datos en una matriz json, la siguiente es la forma:
public string ConvertDataTabletoString() { DataTable dt = new DataTable(); DataTable dt1 = new DataTable(); using (SqlConnection con = new SqlConnection("Data Source=SureshDasari;Initial Catalog=master;Integrated Security=true")) { using (SqlCommand cmd = new SqlCommand("select title=City,lat=latitude,lng=longitude,description from LocationDetails", con)) { con.Open(); SqlDataAdapter da = new SqlDataAdapter(cmd); da.Fill(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; 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); } SqlCommand cmd1 = new SqlCommand("_another_query_", con); SqlDataAdapter da1 = new SqlDataAdapter(cmd1); da1.Fill(dt1); System.Web.Script.Serialization.JavaScriptSerializer serializer1 = new System.Web.Script.Serialization.JavaScriptSerializer(); Dictionary<string, object> row1; foreach (DataRow dr in dt1.Rows) //use the old variable rows only { row1 = new Dictionary<string, object>(); foreach (DataColumn col in dt1.Columns) { row1.Add(col.ColumnName, dr[col]); } rows.Add(row1); // Finally You can add into old json array in this way } return serializer.Serialize(rows); } } }
De la misma manera se puede utilizar para tantas tablas de datos como desee.
fuente
Convierta la tabla de datos a JSON usando C # .net
public static 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[col.ColumnName] = (Convert.ToString(row[col])); } list.Add(dict); } JavaScriptSerializer serializer = new JavaScriptSerializer(); return serializer.Serialize(list); }
fuente
Prueba esta función personalizada.
public static string DataTableToJsonObj(DataTable dt) { DataSet ds = new DataSet(); ds.Merge(dt); StringBuilder jsonString = new StringBuilder(); if (ds.Tables[0].Rows.Count > 0) { jsonString.Append("["); for (int rows = 0; rows < ds.Tables[0].Rows.Count; rows++) { jsonString.Append("{"); for (int cols = 0; cols < ds.Tables[0].Columns.Count; cols++) { jsonString.Append(@"""" + ds.Tables[0].Columns[cols].ColumnName + @""":"); /* //IF NOT LAST PROPERTY if (cols < ds.Tables[0].Columns.Count - 1) { GenerateJsonProperty(ds, rows, cols, jsonString); } //IF LAST PROPERTY else if (cols == ds.Tables[0].Columns.Count - 1) { GenerateJsonProperty(ds, rows, cols, jsonString, true); } */ var b = (cols < ds.Tables[0].Columns.Count - 1) ? GenerateJsonProperty(ds, rows, cols, jsonString) : (cols != ds.Tables[0].Columns.Count - 1) || GenerateJsonProperty(ds, rows, cols, jsonString, true); } jsonString.Append(rows == ds.Tables[0].Rows.Count - 1 ? "}" : "},"); } jsonString.Append("]"); return jsonString.ToString(); } return null; } private static bool GenerateJsonProperty(DataSet ds, int rows, int cols, StringBuilder jsonString, bool isLast = false) { // IF LAST PROPERTY THEN REMOVE 'COMMA' IF NOT LAST PROPERTY THEN ADD 'COMMA' string addComma = isLast ? "" : ","; if (ds.Tables[0].Rows[rows][cols] == DBNull.Value) { jsonString.Append(" null " + addComma); } else if (ds.Tables[0].Columns[cols].DataType == typeof(DateTime)) { jsonString.Append(@"""" + (((DateTime)ds.Tables[0].Rows[rows][cols]).ToString("yyyy-MM-dd HH':'mm':'ss")) + @"""" + addComma); } else if (ds.Tables[0].Columns[cols].DataType == typeof(string)) { jsonString.Append(@"""" + (ds.Tables[0].Rows[rows][cols]) + @"""" + addComma); } else if (ds.Tables[0].Columns[cols].DataType == typeof(bool)) { jsonString.Append(Convert.ToBoolean(ds.Tables[0].Rows[rows][cols]) ? "true" : "fasle"); } else { jsonString.Append(ds.Tables[0].Rows[rows][cols] + addComma); } return true; }
fuente
Para acceder al valor de conversión de tabla de datos en el método Json, siga los pasos a continuación:
$.ajax({ type: "POST", url: "/Services.asmx/YourMethodName", data: "{}", contentType: "application/json; charset=utf-8", dataType: "json", success: function (data) { var parsed = $.parseJSON(data.d); $.each(parsed, function (i, jsondata) { $("#dividtodisplay").append("Title: " + jsondata.title + "<br/>" + "Latitude: " + jsondata.lat); }); }, error: function (XHR, errStatus, errorThrown) { var err = JSON.parse(XHR.responseText); errorMessage = err.Message; alert(errorMessage); } });
fuente
Muy simple en estos días ..
string json = JsonConvert.SerializeObject(YourDataTable, Formatting.Indented);
Ahora convierta su Json en una DataTable:
YourDataTable = (DataTable)JsonConvert.DeserializeObject(json, (typeof(DataTable)));
Funciona también para DataSets.
fuente
Tengo una función simple para convertir la tabla de datos a una cadena json.
He usado Newtonsoft para generar cadenas. No uso Newtonsoft para serializar completamente Datatable. Tenga cuidado con esto.
Quizás esto pueda ser útil.
private string DataTableToJson(DataTable dt) { if (dt == null) { return "[]"; }; if (dt.Rows.Count < 1) { return "[]"; }; JArray array = new JArray(); foreach(DataRow dr in dt.Rows) { JObject item = new JObject(); foreach(DataColumn col in dt.Columns) { item.Add(col.ColumnName, dr[col.ColumnName]?.ToString()); } array.Add(item); } return array.ToString(Newtonsoft.Json.Formatting.Indented); }
fuente
prueba esto (ExtensionMethods):
public static string ToJson(this DataTable dt) { List<Dictionary<string, object>> lst = new List<Dictionary<string, object>>(); Dictionary<string, object> item; foreach (DataRow row in dt.Rows) { item = new Dictionary<string, object>(); foreach (DataColumn col in dt.Columns) { item.Add(col.ColumnName, (Convert.IsDBNull(row[col]) ? null : row[col])); } lst.Add(item); } return Newtonsoft.Json.JsonConvert.SerializeObject(lst); }
y use:
DataTable dt = new DataTable(); . . . var json = dt.ToJson();
fuente
Con Cinchoo ETL , una biblioteca de código abierto, puede exportar DataTable a JSON fácilmente con pocas líneas de código
StringBuilder sb = new StringBuilder(); string connectionstring = @"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Northwind;Integrated Security=True"; using (var conn = new SqlConnection(connectionstring)) { conn.Open(); var comm = new SqlCommand("SELECT * FROM Customers", conn); SqlDataAdapter adap = new SqlDataAdapter(comm); DataTable dt = new DataTable("Customer"); adap.Fill(dt); using (var parser = new ChoJSONWriter(sb)) parser.Write(dt); } Console.WriteLine(sb.ToString());
Salida:
{ "Customer": [ { "CustomerID": "ALFKI", "CompanyName": "Alfreds Futterkiste", "ContactName": "Maria Anders", "ContactTitle": "Sales Representative", "Address": "Obere Str. 57", "City": "Berlin", "Region": null, "PostalCode": "12209", "Country": "Germany", "Phone": "030-0074321", "Fax": "030-0076545" }, { "CustomerID": "ANATR", "CompanyName": "Ana Trujillo Emparedados y helados", "ContactName": "Ana Trujillo", "ContactTitle": "Owner", "Address": "Avda. de la Constitución 2222", "City": "México D.F.", "Region": null, "PostalCode": "05021", "Country": "Mexico", "Phone": "(5) 555-4729", "Fax": "(5) 555-3745" } ] }
fuente
public static string ConvertIntoJson(DataTable dt) { var jsonString = new StringBuilder(); if (dt.Rows.Count > 0) { jsonString.Append("["); for (int i = 0; i < dt.Rows.Count; i++) { jsonString.Append("{"); for (int j = 0; j < dt.Columns.Count; j++) jsonString.Append("\"" + dt.Columns[j].ColumnName + "\":\"" + dt.Rows[i][j].ToString().Replace('"','\"') + (j < dt.Columns.Count - 1 ? "\"," : "\"")); jsonString.Append(i < dt.Rows.Count - 1 ? "}," : "}"); } return jsonString.Append("]").ToString(); } else { return "[]"; } } public static string ConvertIntoJson(DataSet ds) { var jsonString = new StringBuilder(); jsonString.Append("{"); for (int i = 0; i < ds.Tables.Count; i++) { jsonString.Append("\"" + ds.Tables[i].TableName + "\":"); jsonString.Append(ConvertIntoJson(ds.Tables[i])); if (i < ds.Tables.Count - 1) jsonString.Append(","); } jsonString.Append("}"); return jsonString.ToString(); }
fuente
//Common DLL client, server public class transferDataTable { public class myError { public string Message { get; set; } public int Code { get; set; } } public myError Error { get; set; } public List<string> ColumnNames { get; set; } public List<string> DataTypes { get; set; } public List<Object> Data { get; set; } public int Count { get; set; } } public static class ExtensionMethod { public static transferDataTable LoadData(this transferDataTable transfer, DataTable dt) { if (dt != null) { transfer.DataTypes = new List<string>(); transfer.ColumnNames = new List<string>(); foreach (DataColumn c in dt.Columns) { transfer.ColumnNames.Add(c.ColumnName); transfer.DataTypes.Add(c.DataType.ToString()); } transfer.Data = new List<object>(); foreach (DataRow dr in dt.Rows) { foreach (DataColumn col in dt.Columns) { transfer.Data.Add(dr[col] == DBNull.Value ? null : dr[col]); } } transfer.Count = dt.Rows.Count; } return transfer; } public static DataTable GetDataTable(this transferDataTable transfer, bool ConvertToLocalTime = true) { if (transfer.Error != null || transfer.ColumnNames == null || transfer.DataTypes == null || transfer.Data == null) return null; int columnsCount = transfer.ColumnNames.Count; DataTable dt = new DataTable(); for (int i = 0; i < columnsCount; i++ ) { Type colType = Type.GetType(transfer.DataTypes[i]); dt.Columns.Add(new DataColumn(transfer.ColumnNames[i], colType)); } int index = 0; DataRow row = dt.NewRow(); foreach (object o in transfer.Data) { if (ConvertToLocalTime && o != null && o.GetType() == typeof(DateTime)) { DateTime dat = Convert.ToDateTime(o); row[index] = dat.ToLocalTime(); } else row[index] = o == null ? DBNull.Value : o; index++; if (columnsCount == index) { index = 0; dt.Rows.Add(row); row = dt.NewRow(); } } return dt; } } //Server [OperationContract] [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest, UriTemplate = "json/data")] transferDataTable _Data(); public transferDataTable _Data() { try { using (SqlConnection con = new SqlConnection(ConfigurationManager.AppSettings["myConnString"])) { con.Open(); DataSet ds = new DataSet(); SqlDataAdapter myAdapter = new SqlDataAdapter("SELECT * FROM tbGalleries", con); myAdapter.Fill(ds, "table"); DataTable dt = ds.Tables["table"]; return new transferDataTable().LoadData(dt); } } catch(Exception ex) { return new transferDataTable() { Error = new transferDataTable.myError() { Message = ex.Message, Code = ex.HResult } }; } } //Client Response = Vossa.getAPI(serviceUrl + "json/data"); transferDataTable transfer = new JavaScriptSerializer().Deserialize<transferDataTable>(Response); if (transfer.Error == null) { DataTable dt = transfer.GetDataTable(); dbGrid.ItemsSource = dt.DefaultView; } else MessageBox.Show(transfer.Error.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
fuente
Pasar el datable a este método devolvería json String.
public DataTable GetTable() { string str = "Select * from GL_V"; OracleCommand cmd = new OracleCommand(str, con); cmd.CommandType = CommandType.Text; DataTable Dt = OracleHelper.GetDataSet(con, cmd).Tables[0]; return Dt; } public string DataTableToJSONWithJSONNet(DataTable table) { string JSONString = string.Empty; JSONString = JsonConvert.SerializeObject(table); return JSONString; } public static DataSet GetDataSet(OracleConnection con, OracleCommand cmd) { // create the data set DataSet ds = new DataSet(); try { //checking current connection state is open if (con.State != ConnectionState.Open) con.Open(); // create a data adapter to use with the data set OracleDataAdapter da = new OracleDataAdapter(cmd); // fill the data set da.Fill(ds); } catch (Exception ex) { throw; } return ds; }
fuente
Estoy usando esta función para describir la tabla.
Úselo después de completar la tabla de datos
static public string DataTableToJSON(DataTable dataTable,bool readableformat=true) { string JSONString="["; string JSONRow; string colVal; foreach(DataRow dataRow in dataTable.Rows) { if(JSONString!="[") { JSONString += ","; } JSONRow = ""; if (readableformat) { JSONRow += "\r\n"; } JSONRow += "{"; foreach (DataColumn col in dataTable.Columns) { colVal = dataRow[col].ToString(); colVal = colVal.Replace("\"", "\\\""); colVal = colVal.Replace("'", "\\\'"); if(JSONRow!="{"&&JSONRow!="\r\n{") { JSONRow += ","; } JSONRow += "\"" + col.ColumnName + "\":\"" + colVal + "\""; } JSONRow += "}"; JSONString += JSONRow; } JSONString += "\r\n]"; return JSONString; }
Consulta MySQL: "DESCRIBE TableName;"; Salida de ejemplo de DataTableToJSON (dataTable):
[ {"Field":"id","Type":"int(5)","Null":"NO","Key":"PRI","Default":"","Extra":"auto_increment"}, {"Field":"ad","Type":"int(11) unsigned","Null":"NO","Key":"MUL","Default":"","Extra":""}, {"Field":"soyad","Type":"varchar(20)","Null":"YES","Key":"","Default":"","Extra":""}, {"Field":"ulke","Type":"varchar(20)","Null":"YES","Key":"","Default":"","Extra":""}, {"Field":"alan","Type":"varchar(20)","Null":"YES","Key":"","Default":"","Extra":""}, {"Field":"numara","Type":"varchar(20)","Null":"NO","Key":"","Default":"","Extra":""} ]
Probado con PHP:
$X='[ {"Field":"id","Type":"int(5)","Null":"NO","Key":"PRI","Default":"","Extra":"auto_increment"}, {"Field":"ad","Type":"int(11) unsigned","Null":"NO","Key":"MUL","Default":"","Extra":""}, {"Field":"soyad","Type":"varchar(20)","Null":"YES","Key":"","Default":"","Extra":""}, {"Field":"ulke","Type":"varchar(20)","Null":"YES","Key":"","Default":"","Extra":""}, {"Field":"alan","Type":"varchar(20)","Null":"YES","Key":"","Default":"","Extra":""}, {"Field":"numara","Type":"varchar(20)","Null":"NO","Key":"","Default":"","Extra":""} ]'; $Y=json_decode($X,true); echo $Y[0]["Field"]; var_dump($Y);
fuente
¡Todas estas respuestas son realmente excelentes para mover datos! Donde fallan es preservando el tipo de columna de datos que se mueven. Esto se convierte en un problema cuando desea hacer cosas como fusionar tablas de datos que parecen ser iguales.
JsonConvert
mirará la primera fila de datos para determinar el tipo de datos de la columna, que puede adivinarse incorrectamente.Para evitar esto;
DataTable
yDataColumn
definiciones de en objetos de respuesta separados.DataColumn
definiciones en la respuesta antes de leer en la tabla.DataTable
ignorando el esquema definido por Json.Parece mucho, pero son solo tres líneas adicionales de código.
// Get our Column definitions and serialize them using an anoymous function. var columns = dt.Columns.Cast<DataColumn>().Select(c => new { DataPropertyName = c.ColumnName, DataPropertyType = c.DataType.ToString()}); resp.ObjSchema = JsonConvert.SerializeObject(columns); resp.Obj = JsonConvert.SerializeObject(dt);
resp.ObjSchema
se convierte en;[ { "DataPropertyName": "RowId", "DataPropertyType ": "System.Int32" }, { "DataPropertyName": "ItemName", "DataPropertyType ": "System.String" } ]
En lugar de dejar que Json defina las definiciones de columna a través de
dt = JsonConvert.DeserializeObject<DataTable>(response)
, podemos usar LINQ en nuestroresp.ObjSchema
para definirlas nosotros mismos. UsaremosMissingSchemaAction.Ignore
para ignorar el esquema proporcionado por Json.// If your environment does not support dynamic you'll need to create a class for with DataPropertyName and DataPropertyType. JsonConvert.DeserializeObject<List<dynamic>>(response.ObjSchema).ForEach(prop => { dt.Columns.Add(new DataColumn() { ColumnName = prop.DataPropertyName, DataType = Type.GetType(prop.DataPropertyType.ToString()) }); }); // Merge the results ignoring the JSON schema. dt.Merge(JsonConvert.DeserializeObject<DataTable>(response.Obj), true, MissingSchemaAction.Ignore);
fuente