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

27
demandé sur Rawhi 2011-02-22 23:41:03

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);
}
48
répondu Jonathan 2013-04-23 10:17:44

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!

10
répondu David Hoerster 2017-12-13 00:29:53

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:

9
répondu Eric Patrick 2018-02-23 15:22:00

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);
7
répondu Chandu 2016-06-17 19:10:45

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;
}
5
répondu gerzalez 2017-05-04 15:37:28

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);
3
répondu lsibaja 2017-05-23 12:03:06

ç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..

1
répondu BenW 2016-03-10 04:26:23

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.

1
répondu Jenna Leaf 2016-06-17 19:07:46

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.

1
répondu Abdul Rehman Sayed 2017-05-23 11:54:43

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.

1
répondu Muhammad Saqib 2018-07-03 17:18:38

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;
    }
0
répondu Amjad Abu Saa 2013-09-29 07:04:10

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);
0
répondu shiva yekta 2016-11-16 11:23:46

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"
 }
]
0
répondu RajN 2018-07-03 17:30:10