web-dev-qa-db-ger.com

konvertieren von SqlDataReader in 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();
}

Ich verwende hier meine eigene Funktion zur Serialisierung. Ich muss wissen, ob dies ein guter Weg ist oder ich sollte einen anderen verwenden. Übrigens habe ich versucht, die JavaScriptSerializer zu verwenden, aber das funktionierte nicht mit SqlDataReader. thanx 

29
Rawhi

Wenn Sie etwas möchten, das in beliebige JSON-Dateien konvertiert werden kann, können Sie es konvertieren, indem Sie es in ein Dictionary (von String, Objekt) folgendermaßen serialisieren:

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;
}

Und dann verwenden Sie das NewtonSoft.Json JsonConvert-Objekt, um Ihre JSON zu erhalten:

var r = Serialize(reader);
string json = JsonConvert.SerializeObject(r, Formatting.Indented);

UPDATE: Wenn Sie nur integrierte Methoden verwenden möchten und MVC verwenden, können Sie die integrierte Json-Helper-Methode für Ihre neu serialisierte Anwendung verwenden:

JsonResult Index(int id) {
    var r = Serialize(reader);
    return Json(r, JsonRequestBehavior.AllowGet);
}
51
Jonathan

Ich stoße auf Anwendungsfälle, bei denen die Anzahl der vom Datenleser zurückgegebenen Zeilen hinsichtlich des Speicherverbrauchs problematisch werden kann. Der folgende Code verwendet einen JsonWriter (von JSON.NET) über einen Stream. Sicher kann man den Nutzen riesiger JSON-Dokumente diskutieren, aber manchmal werden unsere Anwendungsfälle von anderen diktiert :-)

Ein paar Anmerkungen:

  • Mein SqlDataReader kann mehrere Ergebnismengen ('Tabellen') enthalten.
  • Ich kann die Ausgabe an einen FileStream- oder einen HttpResponse-Stream senden
  • Ich habe meine Objektnamen "abstrahiert", um mit der ersten Spalte übereinzustimmen, die pro Ergebnismenge zurückgegeben wird
  • Wegen des Potenzials für große Ergebnismengen verwende ich async-Methoden des SqlDataReader.
  • Ich lasse JSON.NET das gesamte Serialisierungsproblem der in den Datenleserergebnissen enthaltenen tatsächlichen Daten handhaben.

Der 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();
}

Ein Beispiel für eine heterogene Ausgabe wäre:

{
    "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.",
            }
        ]
    }
}

Referenz:

13
Eric Patrick

Eine weitere Option wäre die Verwendung der ausgezeichneten JSON.NET-Bibliothek von James Newton-King - http://www.newtonsoft.com/json

Hier ein kurzes Beispiel, wie man eine Sammlung aufbaut und als JSON-serialisierte Zeichenfolge ausgibt:

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();
    }
}

Sie können dasselbe mit Ihrer Schleife tun, indem Sie jede Zeile Ihres SqlDataReader in ein anonymes Objekt einlesen und es anschließend mit JSON.NET zu einer Zeichenfolge serialisieren.

Hoffe das hilft!

11
David Hoerster

Versuche dies:

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
Chandu

Dies sollte die Arbeit erledigen

private String sqlDatoToJson(SqlDataReader dataReader)
{
    var dataTable = new DataTable();
    dataTable.Load(dataReader);
    string JSONString = string.Empty;
    JSONString = JsonConvert.SerializeObject(dataTable);
    return JSONString;
}
5
gerzalez

Ich benutze diesen Code, basierend auf Jonathans Antwort :

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;
}

Und dann:

var rows = this.ConvertToDictionary(reader);

return JsonConvert.SerializeObject(rows, Formatting.Indented);
3
Lenin

Neben Jonathan Answer hatte ich in ASP.NET Core eine ähnliche Anforderung, das Ergebnis eines SQLDataReader-Objekts in einen JSON-String oder ein Ergebnisobjekt () Umzuwandeln.

 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;
        }
    }

& benutzte es gemäß meiner Anforderung als: 

var result = await reader.GetSerialized(); //to get the result object

oder

string strResult = await reader.toJSON(); //to get the result string

Ich habe eine asynchrone Methode erstellt, weil ich einige andere Dinge tun musste, bis das Lesen aus der Datenbank abgeschlossen war.

1

Seit SQL Server 2016 hat Microsoft dieses Feature in SQL-Abfragen eingebettet. Sie können dies erreichen, indem Sie am Ende Ihrer Abfragen das Schlüsselwort FOR JSON verwenden.

select * from table_example where somecolumn = somecondition FOR JSON AUTO

weitere Informationen und Beispiele finden Sie in den offiziellen Dokumenten. JSON-Ausgabe automatisch mit AUTO-Modus (SQL Server) formatieren

Hier ist das C # -Codebeispiel von Microsoft, um JSON-Zeichenfolge aus SQL-Abfragen abzurufen.

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());
    }
}

Warnung: Diese Lösung ist nur für SQL SERVER 2016 und höher gültig.

1
Muhammad Saqib

Dies dient zur Verbesserung der Linq-Antwort von Chandu, die die Abfragesyntax verwendet (von ... select ...). Wenn Sie die Methodensyntax bevorzugen, finden Sie hier Ihre Antwort.

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); 

Ich hoffe es hilft jemandem.

1
Jenna Leaf

Das kann nicht so schwer sein. Dies ist, was ich getan habe, wenn ich Suchergebnisse als JSON an eine Webseite zurückgeben möchte.

Zuerst haben Sie eine Klasse wie diese

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; }
}

und dann den Code unten.

        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);

das funktioniert für mich sehr gut ..

1
BenW

Mit Cinchoo ETL - einer Open-Source-Bibliothek können Sie SqlDataReader mit wenigen Codezeilen problemlos in JSON exportieren

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());

Ausgabe:

[
 {
  "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
RajN

Ich habe die folgende Methode erstellt, bei der ein beliebiger DataReader in JSON konvertiert wird, jedoch nur für die Serialisierung einzelner Tiefe:

sie sollten den Reader und die Spaltennamen als String-Array übergeben, zum Beispiel:

String [] columns = {"CustomerID", "CustomerName", "CustomerDOB"};

dann rufen Sie die Methode auf

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
Amjad Abu Saa

fügen Sie dem Projekt dann die Referenz: System.Web.Extensions hinzu

using System.Web.Script.Serialization;

in C # -Code können Sie schreiben:

 var json = new JavaScriptSerializer().Serialize(obj);
0
shiva yekta