От DataTable в C#.NET в JSON
Я довольно новичок в C# и .NET, но я сделал этот код для вызова хранимой процедуры, а затем я хочу взять возвращаемый DataTable и преобразовать его в JSON.
SqlConnection con = new SqlConnection("connection string here");
SqlDataAdapter da = new SqlDataAdapter();
SqlCommand cmd = new SqlCommand("getDates", con);
SqlParameter par = new SqlParameter("@PlaceID", SqlDbType.Int);
par.Value = 42;
da.SelectCommand = cmd;
cmd.Parameters.Add(par);
DataSet ds = new DataSet();
DataTable dt = new DataTable();
con.Open();
try{
cmd.CommandType = CommandType.StoredProcedure;
da.Fill(ds);
}
мой вопрос в том, что является лучшим / самым простым способом сделать это? Пример был бы отличным, поскольку я все еще очень новичок в этом.
7 ответов
вместо datatable вы должны использовать datareader. Ваш код неэффективен и несколько трудно читается - вы можете сделать что-то вроде этого:
StringBuilder json = new StringBuilder();
using(SqlConnection cnn = new SqlConnection(your_connection_string))
{
cnn.open();
using(SqlCommand cmd = new SqlCommand("name_of_stored_procedure", cnn))
{
cmd.Paramters.AddWithValue("@Param", "value");
using(SqlDataReader reader = cmd.ExecuteReader())
{
while(reader.Read())
{
json.AppendFormat("{{\"name\": \"{0}\"}}", reader["name"]);
}
}
}
cnn.close();
}
затем вы можете использовать json.ToString
чтобы получить outpt
хотя JavaScriptSerializer (система.Сеть.Скрипт.Сериализация.JavaScriptSerializer) не может преобразовать DataTable непосредственно в JSON, можно распаковать DataTable в список, который затем может быть сериализован.
следующая функция преобразует произвольный объект DataTable в строку JSON (без предварительного знания имен полей или типов данных):
public static string 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] = row[col];
}
list.Add(dict);
}
JavaScriptSerializer serializer = new JavaScriptSerializer();
return serializer.Serialize(list);
}
вы можете использовать JSON.NET библиотека:http://json.codeplex.com/ для сериализации / десериализации объекта DataTable.
string json = JsonConvert.SerializeObject(table);
который сериализуется к чему-то вроде этого:
[ { "Column1": "Row Value", "Column2": "2" } ]
Если вам нужно сериализовать больше информации о DataTable например, схема столбца, первичный ключ, имя таблицы, то вы можете использовать пользовательский конвертер, который я написал:https://github.com/chris-herring/DataTableConverter. Используйте его так:
string json = JsonConvert.SerializeObject(table, new Serialization.DataTableConverter());
DataTable table = JsonConvert.DeserializeObject<DataTable>(json, new Serialization.DataTableConverter());
что сериализуется примерно так:
{
"TableName": "TestTable",
"Columns": [
{
"AllowDBNull": false,
"AutoIncrement": true,
"AutoIncrementSeed": 2,
"AutoIncrementStep": 1,
"Caption": "PrimaryKey",
"ColumnName": "PrimaryKey",
"DataType": "Int32",
"DateTimeMode": "UnspecifiedLocal",
"DefaultValue": null,
"MaxLength": -1,
"Ordinal": 0,
"ReadOnly": false,
"Unique": true
}
],
"Rows": [
[
1
],
[
2
],
[
3
]
],
"PrimaryKey": ["PrimaryKey"]
}
Спасибо Ариэль. Ваш ответ был очень полезен. Вот версия, которая основывается на вашем ответе.
public string ReadToJson(SqlDataReader reader)
{
List<string> cols = new List<string>(10);
int ncols = reader.FieldCount;
for (int i = 0; i < ncols; ++i)
{
cols.Add(reader.GetName(i));
}
StringBuilder sbJson = new StringBuilder("[");
//process each row
while (reader.Read())
{
sbJson.Append("{");
foreach (string col in cols)
{
sbJson.AppendFormat("\"{0}\":{1}, ", col, reader[col]);
}
sbJson.Replace(", ", "},", sbJson.Length - 2, 2);
}
sbJson.Replace("},", "}]", sbJson.Length - 2, 2);
return sbJson.ToString();
}
спасибо Карл Венцель. У меня была проблема, когда я мог получить таблицу данных только из старого веб-сервиса asmx. Теперь я написал веб-страницу, которая может анализировать этот DataTable и возвращать его в JSON.
public static string DataTableToJSON(DataTable table)
{
List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();
foreach (DataRow row in table.Rows)
{
Dictionary<string, object> dict = new Dictionary<string, object>();
foreach (DataColumn col in table.Columns)
{
dict[col.ColumnName] = row[col];
}
list.Add(dict);
}
JavaScriptSerializer serializer = new JavaScriptSerializer();
return serializer.Serialize(list);
}
альтернативный способ без использования сериализатора 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());
}
//Function 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]", "");
}
Я использую JavaScriptSerializer + LINQ
return new JavaScriptSerializer().Serialize(
dataTable.Rows.Cast<DataRow>()
.Select(row => row.Table.Columns.Cast<DataColumn>()
.ToDictionary(col => col.ColumnName, col => row[col.ColumnName]))
.ToList()
);