从SqlDataReader创建JSON字符串

11

更新

我已经想通了。请查看下面的答案


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

这个问题由烦人的注释/******** ********/标记。

// 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 构建一个准备通过 HTTP 响应返回的 JSON 字符串?

如果需要我进行澄清,请告诉我。

4个回答

21

我的版本:

这个版本没有使用DataSchema,而且将结果装入一个数组中,而不是对每一行使用一个writer。

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

6

针对特定示例进行编辑:

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上的示例。您还可以在该页面上查看其他类似的方法。 - Code Maverick
@Scott...太棒了!我会把这个整合起来。一旦我恢复了我的点赞特权,我会给你一个+1。 - Hristo
1
@Hristo - 让我再次为您编辑答案。我以前从未使用过Json.NET,但我会编辑成我会尝试的方式。 - Code Maverick
@Scott...非常感谢。慢慢来,我也不会在周五之前处理这个问题。 - Hristo
1
@Hristo - 没问题,告诉我...我也很感兴趣!祝你好运。 - Code Maverick
显示剩余8条评论

4

明白了!这是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

这个答案和 https://dev59.com/3m035IYBdhLWcg3wNtNw#14818354 上的那个结合起来解决了我的问题!非常感谢。 - Deep in the Code
如果您的数据读取器中有多行数据,那么这会在JSON响应中给您一个对象数组吗?例如:[{ "row1-col1":"dataABC", "row1col2":"dataDEF" }, { "row2col1": "more data", "row2col2": "even more" }] - 我有点惊讶微软在.NET 4.5+中没有提供内置方法来实现这个... - JaKXz

0
我创建了以下方法,它可以将任何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 对象或类似的东西,否则你会一遍又一遍地重建整个字符串并复制它。 - mike

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接