【问题标题】:create JSON string from SqlDataReader从 SqlDataReader 创建 JSON 字符串
【发布时间】:2011-04-05 15:36:24
【问题描述】:

更新

我想通了。 Check out my answer below.


我正在尝试创建一个 JSON 字符串来表示数据库表中的一行以在 HTTP 响应中返回。似乎Json.NET 将是一个很好的工具。但是,我不确定如何构建 JSON 字符串我正在从数据库中读取。

问题被讨厌的cmets标记/******** ********/

// connect to DB
theSqlConnection.Open(); // open the connection

SqlDataReader reader = sqlCommand.ExecuteReader();
if (reader.HasRows) {

    while(reader.Read()) {

        StringBuilder sb = new StringBuilder();
        StringWriter sw = new StringWriter(sb);

        using (JsonWriter jsonWriter = new JsonTextWriter(sw)) {

            // read columns from the current row and build this JsonWriter
            jsonWriter.WriteStartObject();
            jsonWriter.WritePropertyName("FirstName");

            // I need to read the value from the database
/******** I can't just say reader[i] to get the ith column. How would I loop here to get all columns? ********/
            jsonWriter.WriteValue(... ? ...);
            jsonWriter.WritePropertyName("LastName");
            jsonWriter.WriteValue(... ? ...);
            jsonWriter.WritePropertyName("Email");
            jsonWriter.WriteValue(... ? ...);

            // etc...
            jsonWriter.WriteEndObject();
        }
    }
}

问题是我不知道如何从SqlReader 的行中读取每一列,以便我可以调用WriteValue 并为其提供正确的信息并将其附加到正确的列名。所以如果一行看起来像这样......

| FirstName | LastName | Email |

...我将如何为每个这样的行创建一个JsonWriter,以便它包含该行的所有列名和每列中的相应值,然后使用该JsonWriter 来构建一个准备好的 JSON 字符串用于通过 HTTP 响应返回?

如果我需要澄清任何事情,请告诉我。

【问题讨论】:

    标签: c# asp.net database json json.net


    【解决方案1】:

    我的版本:

    这不使用 DataSchema,还将结果包装在一个数组中,而不是每行使用一个写入器。

    SqlDataReader rdr = cmd.ExecuteReader();
    
    StringBuilder sb = new StringBuilder();
    StringWriter sw = new StringWriter(sb);    
    
    using (JsonWriter jsonWriter = new JsonTextWriter(sw)) 
    {    
        jsonWriter.WriteStartArray();
    
        while (rdr.Read())
        {
            jsonWriter.WriteStartObject();
    
            int fields = rdr.FieldCount;
    
            for (int i = 0; i < fields; i++)
            { 
                jsonWriter.WritePropertyName(rdr.GetName(i));
                jsonWriter.WriteValue(rdr[i]);
            }
    
            jsonWriter.WriteEndObject();
        }
    
        jsonWriter.WriteEndArray();
    }
    

    【讨论】:

    • 非常有帮助!非常感谢!
    【解决方案2】:

    针对具体示例进行了编辑:

    theSqlConnection.Open();
    
    SqlDataReader reader = sqlCommand.ExecuteReader();
    DataTable schemaTable = reader.GetSchemaTable();
    
    foreach (DataRow row in schemaTable.Rows)
    {
        StringBuilder sb = new StringBuilder();
        StringWriter sw = new StringWriter(sb);
    
        using (JsonWriter jsonWriter = new JsonTextWriter(sw)) 
        {    
            jsonWriter.WriteStartObject();
    
            foreach (DataColumn column in schemaTable.Columns)
            {
                jsonWriter.WritePropertyName(column.ColumnName);
                jsonWriter.WriteValue(row[column]);
            }
    
            jsonWriter.WriteEndObject();
        }
    }
    
    theSqlConnection.Close();
    

    【讨论】:

    • 已编辑答案以展示 msdn 的示例。您还可以查看在该页面上执行类似操作的其他方式。
    • @Scott...太棒了!我会把这个放在一起。一旦我恢复了我的投票特权,我会给你一个 +1
    • 显然,从上面您可以推断出如何将其纳入您的特定需求。
    • @Hristo - 让我再次为您编辑答案。我以前从未使用过 Json.NET,但我会编辑我会尝试的内容。
    • @Hristo - 没问题,让我知道......我也有兴趣知道!祝你好运。
    【解决方案3】:

    知道了!这是 C#...

    // ... SQL connection and command set up, only querying 1 row from the table
    StringBuilder sb = new StringBuilder();
    StringWriter sw = new StringWriter(sb);
    JsonWriter jsonWriter = new JsonTextWriter(sw);
    
    try {
    
        theSqlConnection.Open(); // open the connection
    
        // read the row from the table
        SqlDataReader reader = sqlCommand.ExecuteReader();
        reader.Read();
    
        int fieldcount = reader.FieldCount; // count how many columns are in the row
        object[] values = new object[fieldcount]; // storage for column values
        reader.GetValues(values); // extract the values in each column
    
        jsonWriter.WriteStartObject();
        for (int index = 0; index < fieldcount; index++) { // iterate through all columns
    
            jsonWriter.WritePropertyName(reader.GetName(index)); // column name
            jsonWriter.WriteValue(values[index]); // value in column
    
        }
        jsonWriter.WriteEndObject();
    
        reader.Close();
    
    } catch (SqlException sqlException) { // exception
        context.Response.ContentType = "text/plain";
        context.Response.Write("Connection Exception: ");
        context.Response.Write(sqlException.ToString() + "\n");
    } finally {
        theSqlConnection.Close(); // close the connection
    }
    // END of method
    // the above method returns sb and another uses it to return as HTTP Response...
    StringBuilder theTicket = getInfo(context, ticketID);
    context.Response.ContentType = "application/json";
    context.Response.Write(theTicket);
    

    ...所以StringBuilder sb 变量是代表我想要查询的行的 JSON 对象。这里是 JavaScript...

    $.ajax({
        type: 'GET',
        url: 'Preview.ashx',
        data: 'ticketID=' + ticketID,
        dataType: "json",
        success: function (data) {
    
            // data is the JSON object the server spits out
            // do stuff with the data
        }
    });
    

    感谢Scott 的回答,他的回答启发了我找到解决方案。

    Hristo

    【讨论】:

    • 这个答案,结合stackoverflow.com/a/14818354/2079606 的答案解决了我的问题!非常感谢。
    • 如果您的数据阅读器中有多行,这会在您的 JSON 响应中为您提供一个对象数组吗?即[{ "row1-col1":"dataABC", "row1col2":"dataDEF" }, { "row2col1": "more data", "row2col2": "even more" }] - 我有点惊讶微软没有在 .NET 4.5+ 中为此提供内置方法...
    【解决方案4】:

    我做了以下方法,它将任何 DataReader 转换为 JSON,但仅用于单深度序列化:

    你应该将 reader 和列名作为字符串数组传递,例如:

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

    【讨论】:

    • 应该使用StringBuilder 对象或类似的东西,否则你将重建整个字符串并一遍又一遍地复制它
    猜你喜欢
    • 2018-03-07
    • 2014-03-27
    • 2012-12-18
    • 1970-01-01
    • 1970-01-01
    • 2013-07-22
    • 2022-01-22
    • 2011-03-08
    • 1970-01-01
    相关资源
    最近更新 更多