Конвертировать из SqlDataReader в JSON
public string toJSON(SqlDataReader o)
{
StringBuilder s = new StringBuilder();
s.Append("[");
if (o.HasRows)
while (o.Read())
s.Append("{" + '"' + "Id" + '"' + ":" + o["Id"] + ", "
+ '"' + "CN" + '"' + ":" + o["CatName"] + ", "
+ '"' + "Ord" + '"' + ":" + o["Ord"] + ","
+ '"' + "Icon" + '"' + ":" + o["Icon"] + "}, ");
s.Remove(s.Length - 2, 2);
s.Append("]");
o.Close();
return s.ToString();
}
Я использую здесь свою собственную функцию для сериализации. Мне нужно знать, хорошо ли это, или я должен использовать другой. BTW Я попытался использовать JavaScriptSerializer
, но это не сработало с SqlDataReader. thanx
Ответы
Ответ 1
Если вы хотите что-то, что будет конвертировать в произвольный JSON, вы можете конвертировать его путем сериализации в словарь (из строки, объекта):
public IEnumerable<Dictionary<string, object>> Serialize(SqlDataReader reader)
{
var results = new List<Dictionary<string, object>>();
var cols = new List<string>();
for (var i = 0; i < reader.FieldCount; i++)
cols.Add(reader.GetName(i));
while (reader.Read())
results.Add(SerializeRow(cols, reader));
return results;
}
private Dictionary<string, object> SerializeRow(IEnumerable<string> cols,
SqlDataReader reader) {
var result = new Dictionary<string, object>();
foreach (var col in cols)
result.Add(col, reader[col]);
return result;
}
И затем используйте объект NewtonSoft.Json JsonConvert, чтобы получить JSON:
var r = Serialize(reader);
string json = JsonConvert.SerializeObject(r, Formatting.Indented);
UPDATE:
Если вы просто хотите использовать встроенные методы, и вы используете MVC, вы можете использовать встроенный метод помощника Json для вашей новой сериализации:
JsonResult Index(int id) {
var r = Serialize(reader);
return Json(r, JsonRequestBehavior.AllowGet);
}
Ответ 2
Другой вариант - использовать отличную библиотеку JSON.NET от James Newton-King - http://www.newtonsoft.com/json
Вот краткий пример того, как использовать его для создания коллекции, а затем выводить ее как строку, сериализованную JSON:
using Newtonsoft.Json;
class Program
{
static void Main(string[] args)
{
ArrayList objs = new ArrayList();
//get the data reader, etc.
while(o.Read())
{
objs.Add(new
{
Id = o["Id"],
CN = o["CatName"],
Ord = o["Ord"],
Icon = o["Icon"]
});
}
//clean up datareader
Console.WriteLine(JsonConvert.SerializeObject(objs));
Console.ReadLine();
}
}
Вы можете сделать то же самое с вашим циклом, прочитав в каждой строке вашего SqlDataReader анонимный объект, а затем используйте JSON.NET для сериализации его в строку.
Надеюсь, это поможет!
Ответ 3
Я встречаю случаи использования, когда количество строк, возвращаемых считывателем данных, может стать проблематичным в отношении потребления памяти. Следующий код использует JsonWriter (из JSON.NET) поверх потока. Можно, конечно, обсуждать полезность огромных документов JSON, но иногда наши случаи использования продиктованы другими :-)
Несколько примечаний:
- Мой SqlDataReader может содержать несколько наборов результатов ("таблицы")
- Я могу отправлять вывод в поток FileStream или HttpResponse
- Я "абстрагировал" мои имена объектов, чтобы соответствовать первому столбцу, возвращенному в каждом наборе результатов
- Из-за потенциала больших наборов результатов я использую async-методы SqlDataReader.
- Я разрешаю JSON.NET справляться со всей проблемой сериализации фактических данных, содержащихся в результатах чтения данных.
Код:
var stream = ... // In my case, a FileStream or HttpResponse stream
using (var writer = new JsonTextWriter(new StreamWriter(stream)))
{
writer.WriteStartObject();
do
{
int row = 0;
string firstColumn = null;
while (await reader.ReadAsync())
{
if (row++ == 0)
{
firstColumn = reader.GetName(0);
writer.WritePropertyName(string.Format("{0}Collection", firstColumn));
writer.WriteStartArray();
}
writer.WriteStartObject();
for (int i = 0; i < reader.FieldCount; i++)
{
if (!reader.IsDBNull(i)) {
writer.WritePropertyName(reader.GetName(i));
writer.WriteValue(reader.GetValue(i));
}
}
writer.WriteEndObject();
}
writer.WriteEndArray();
} while (await reader.NextResultAsync());
writer.WriteEndObject();
}
Примером гетерогенного вывода будет:
{
"ContactCollection": {
"ContactItem": [{
"ContactID": "1",
"Contact": "Testing",
},
{
"ContactID": "2",
"Contact": "Smith, John",
},
{
"ContactID": "4",
"Contact": "Smith, Jane",
}
],
"MessageItem": [{
"MessageID": "56563",
"Message": "Contract Review Changed",
},
{
"MessageID": "56564",
"Message": " Changed",
},
{
"MessageID": "56565",
"Message": "Contract Review - Estimated Completion Added.",
}
]
}
}
Ссылка:
Ответ 4
Попробуйте следующее:
o = cmd.ExecuteReader();
var dataQuery = from d in o.Cast<DbDataRecord>()
select new
{
Id = (String)d["Id"],
CN = (String)d["CatName"],
Ord = (String)d["Ord"],
Icon = (String)d["Icon"]
};
var data = dataQuery.ToArray();
JavaScriptSerializer serializer = new JavaScriptSerializer();
String jsonData = serializer.Serialize(data);
Ответ 5
Это должно выполнить задание
private String sqlDatoToJson(SqlDataReader dataReader)
{
var dataTable = new DataTable();
dataTable.Load(dataReader);
string JSONString = string.Empty;
JSONString = JsonConvert.SerializeObject(dataTable);
return JSONString;
}
Ответ 6
Я использую этот код на основе ответа Джонатана:
private IEnumerable<Dictionary<string, object>> ConvertToDictionary(IDataReader reader)
{
var columns = new List<string>();
var rows = new List<Dictionary<string, object>>();
for (var i = 0; i < reader.FieldCount; i++)
{
columns.Add(reader.GetName(i));
}
while (reader.Read())
{
rows.Add(columns.ToDictionary(column => column, column => reader[column]));
}
return rows;
}
И затем:
var rows = this.ConvertToDictionary(reader);
return JsonConvert.SerializeObject(rows, Formatting.Indented);
Ответ 7
Это не может быть так сложно. Это то, что я сделал, когда хочу вернуть результаты поиска на веб-страницу как JSON.
Сначала у вас есть класс, подобный этому
public class SearchResult
{
public string model_no { get; set; }
public string result_text { get; set; }
public string url { get; set; }
public string image_url { get; set; }
}
а затем введите код ниже.
string sql_text = "select * from product_master where model_no like @search_string and active=1";
SqlConnection connection = new SqlConnection(sql_constr);
SqlCommand cmd = new SqlCommand(sql_text, connection);
cmd.Parameters.AddWithValue("@search_string", "%" + search_string + "%");
connection.Open();
SqlDataReader rdr = cmd.ExecuteReader();
List<SearchResult> searchresults = new List<SearchResult>();
while (rdr.Read())
{
SearchResult sr = new SearchResult();
sr.model_no = rdr["model_no"].ToString();
sr.result_text = rdr["product_name"].ToString();
sr.url = rdr["url_key"].ToString();
searchresults.Add(sr);
}
connection.Close();
//build json result
return Json(searchresults, JsonRequestBehavior.AllowGet);
это работает для меня очень хорошо..
Ответ 8
Это для улучшения ответа Chandu Linq, использующего синтаксис запроса (из... select...). Если вы предпочитаете синтаксис метода, вот ваш ответ.
drdr = cmd.ExecuteReader();
Record[] recs = drdr.Cast<DbDataRecord>().Select( data=>new Record{
GraphID=(drdr.IsDBNull(0) ? "" : (string)data["LabelX"])
, XAxis=(drdr.IsDBNull(1) ? "1999-09-09 00:00:00" : Convert.ToDateTime(data["XDate"]).ToString("yyyy-MM-dd HH:mm:ss"))
, YVal=(drdr.IsDBNull(2) ? 0 : int.Parse(data["YFreq"].ToString()))
}).ToArray();
MemoryStream mem = new MemoryStream();
DataContractJsonSerializer szr = new DataContractJsonSerializer(typeof(Record[]));
szr.WriteObject(mem, recs);
String jsonData = Encoding.UTF8.GetString(mem.ToArray(), 0, (int)mem.Length);
Надеюсь, это поможет кому-то.
Ответ 9
В дополнение к Ответу Джонатана, у меня было аналогичное требование в ядре ASP.NET для преобразования результата SQLDataReader в строку JSON или объект результата,
поэтому я создал для него метод расширения:
public static class MyExtensions
{
public async static Task<string> toJSON(this SqlDataReader reader)
{
var results = await reader.GetSerialized();
return JsonConvert.SerializeObject(results, Formatting.Indented);
}
public async static Task<IEnumerable<Dictionary<string, object>>> GetSerialized(this SqlDataReader reader)
{
var results = new List<Dictionary<string, object>>();
var cols = new List<string>();
for (var i = 0; i < reader.FieldCount; i++)
cols.Add(reader.GetName(i));
while (await reader.ReadAsync())
results.Add(SerializeRow(cols, reader));
return results;
}
private static Dictionary<string, object> SerializeRow(IEnumerable<string> cols,
SqlDataReader reader)
{
var result = new Dictionary<string, object>();
foreach (var col in cols)
result.Add(col, reader[col]);
return result;
}
}
& использовал его в соответствии с моим требованием:
var result = await reader.GetSerialized(); //to get the result object
или
string strResult = await reader.toJSON(); //to get the result string
Я создал метод async, потому что мне нужно было сделать еще кое-что, пока чтение не будет завершено из базы данных.
Ответ 10
Начиная с SQL Server 2016, Microsoft встроила эту функцию в SQL-запросы. Вы можете достичь этого, используя ключевое слово FOR JSON
в конце ваших запросов.
select * from table_example where somecolumn = somecondition FOR JSON AUTO
для получения более подробной информации и примера вы можете ознакомиться с официальными документами. Формат вывода JSON автоматически с использованием режима AUTO (SQL Server)
Вот пример кода С# от Microsoft, чтобы получить строку JSON из SQL-запросов.
var queryWithForJson = "SELECT ... FOR JSON";
var conn = new SqlConnection("<connection string>");
var cmd = new SqlCommand(queryWithForJson, conn);
conn.Open();
var jsonResult = new StringBuilder();
var reader = cmd.ExecuteReader();
if (!reader.HasRows)
{
jsonResult.Append("[]");
}
else
{
while (reader.Read())
{
jsonResult.Append(reader.GetValue(0).ToString());
}
}
Предупреждение. Это решение применимо только для SQL SERVER 2016 и выше.
Ответ 11
Я сделал следующий метод, когда он преобразует любой DataReader в JSON, но только для сериализации с одной глубиной:
вам следует передать читателю и имена столбцов в виде массива строк, например:
String [] columns = {"CustomerID", "CustomerName", "CustomerDOB"};
затем вызовите метод
public static String json_encode(IDataReader reader, String[] columns)
{
int length = columns.Length;
String res = "{";
while (reader.Read())
{
res += "{";
for (int i = 0; i < length; i++)
{
res += "\"" + columns[i] + "\":\"" + reader[columns[i]].ToString() + "\"";
if (i < length - 1)
res += ",";
}
res += "}";
}
res += "}";
return res;
}
Ответ 12
добавить ссылку: System.Web.Extensions
для проекта
затем
using System.Web.Script.Serialization;
в коде С#, вы можете использовать write:
var json = new JavaScriptSerializer().Serialize(obj);
Ответ 13
С Cinchoo ETL - библиотека с открытым исходным кодом, вы можете легко экспортировать SqlDataReader в JSON с несколькими строками кода
string connectionstring = @"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Northwind;Integrated Security=True";
StringBuilder sb = new StringBuilder();
using (var conn = new SqlConnection(connectionstring))
{
conn.Open();
var comm = new SqlCommand("SELECT top 2 * FROM Customers", conn);
using (var parser = new ChoJSONWriter(sb))
parser.Write(comm.ExecuteReader());
}
Console.WriteLine(sb.ToString());
Выход:
[
{
"CustomerID": "ALFKI",
"CompanyName": "Alfreds Futterkiste",
"ContactName": "Maria Anders",
"ContactTitle": "Sales Representative",
"Address": "Obere Str. 57",
"City": "Berlin",
"Region": {},
"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": {},
"PostalCode": "05021",
"Country": "Mexico",
"Phone": "(5) 555-4729",
"Fax": "(5) 555-3745"
}
]