conversion de SqlDataReader en 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();
}
j'utilise ici ma propre fonction pour faire de la sérialisation . J'ai besoin de savoir si c'est une bonne façon ou je devrais utiliser un autre . BTW j'ai essayé d'utiliser le JavaScriptSerializer
mais cela n'a pas fonctionné avec SqlDataReader . merci
13 réponses
si vous voulez quelque chose qui va se convertir en JSON arbitraire, vous pouvez le convertir en le sérialisant dans un dictionnaire(de chaîne, d'objet) thusly:
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;
}
puis utilisez le NewtonSoft.Objet Json JsonConvert pour obtenir votre JSON:
var r = Serialize(reader);
string json = JsonConvert.SerializeObject(r, Formatting.Indented);
mise à jour: Si vous voulez juste utiliser des méthodes intégrées, et que vous utilisez MVC, vous pouvez utiliser la méthode JSON helper intégrée sur votre nouvelle sérialisée:
JsonResult Index(int id) {
var r = Serialize(reader);
return Json(r, JsonRequestBehavior.AllowGet);
}
une autre option serait d'utiliser l'excellent JSON.NET bibliothèque -http://www.newtonsoft.com/json
Voici un exemple rapide sur la façon de l'utiliser pour créer une collection, puis sortie comme un JSON-chaîne sérialisée:
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();
}
}
Vous pouvez faire la même chose avec votre boucle en lisant dans chaque ligne de votre SqlDataReader dans un objet anonyme et puis utiliser JSON.NET pour le sérialiser en chaîne.
espérons que cela aide!
je rencontre des cas d'utilisation où le nombre de lignes retournées par le lecteur de données peut devenir problématique en ce qui concerne la consommation de mémoire. Le code suivant utilise un JsonWriter (de JSON.NET) au-dessus d'un ruisseau. On peut certainement débattre de l'utilité d'énormes documents JSON, mais parfois nos cas d'utilisation sont dictés par d'autres: -)
quelques remarques:
- Mon SqlDataReader peut contenir plusieurs jeux de résultats ("tables")
- il se peut que j'envoie la sortie à un FileStream ou à un flux HttpResponse
- j'ai "résumé" mes noms d'objets pour correspondre à la première colonne retournée par jeu de résultats
- en raison du potentiel de grands ensembles de résultats, j'utilise les méthodes async du SqlDataReader.
- je laisse JSON.NET gérer tous les problèmes de sérialisation des données réelles contenues dans les résultats du lecteur de données.
le code:
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.",
}
]
}
}
Référence:
essaye ceci:
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);
Ceci devrait faire l'affaire
private String sqlDatoToJson(SqlDataReader dataReader)
{
var dataTable = new DataTable();
dataTable.Load(dataReader);
string JSONString = string.Empty;
JSONString = JsonConvert.SerializeObject(dataTable);
return JSONString;
}
j'utilise ce code, basé sur la réponse de Jonathan:
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;
}
puis:
var rows = this.ConvertToDictionary(reader);
return JsonConvert.SerializeObject(rows, Formatting.Indented);
ça ne doit pas être si dur. C'est ce que j'ai fait quand je veux retourner les résultats de recherche à une page web comme JSON.
tout d'Abord, avoir une classe comme ceci
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; }
}
et ensuite avoir le code ci-dessous.
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);
cela fonctionne très bien pour moi..
ceci est pour améliorer la réponse Linq de Chandu qui utilise la syntaxe de requête (from ... sélectionner. ..). Si vous préférez la syntaxe de la méthode, voici votre réponse.
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);
j'Espère que ça aide quelqu'un.
plus loin vers Jonathan est réponse, j'avais une exigence similaire dans ASP.NET Core pour convertir le résultat D'un SQLDataReader en une chaîne JSON ou un objet résultat, j'ai donc créé une méthode d'extension pour :
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;
}
}
et utilisé que par mon exigence :
var result = await reader.GetSerialized(); //to get the result object
ou
string strResult = await reader.toJSON(); //to get the result string
j'ai créé une méthode asynchrone, car j'avais d'autres choses à faire jusqu'à la lecture en était fini de la base de données.
depuis SQL Server 2016, Microsoft a intégré cette fonctionnalité avec des requêtes sql. Vous pouvez la réaliser à l'aide de FOR JSON
mot-clé à la fin de vos requêtes.
select * from table_example where somecolumn = somecondition FOR JSON AUTO
pour plus de détails et d'exemples, vous pouvez consulter ces documents officiels formater la sortie JSON automatiquement en Mode AUTO (SQL Server)
Ici est l'exemple de code C de Microsoft pour obtenir la chaîne JSON des requêtes 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());
}
}
Attention: Cette solution est valable uniquement pour SQL SERVER 2016 et plus.
j'ai fait la méthode suivante où il convertit N'importe quel DataReader en JSON, mais seulement pour la sérialisation de profondeur simple:
vous devez passer le lecteur, et les noms de colonne comme un tableau de chaîne, par exemple:
String [] columns = {"CustomerID", "CustomerName", "CustomerDOB"};
alors appelez la méthode
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;
}
ajouter la référence:System.Web.Extensions
pour projet
puis
using System.Web.Script.Serialization;
dans le code c#, vous pouvez écrire :
var json = new JavaScriptSerializer().Serialize(obj);
Cinchoo ETL - une bibliothèque open source, vous pouvez exporter SqlDataReader vers JSON facilement avec quelques lignes de code
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());
Sortie:
[
{
"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"
}
]