C#中SqlDataReader序列化为Json对象失败,如何解决?
解决SqlDataReader序列化为结构化JSON的问题
我明白你遇到的困扰了——直接序列化SqlDataReader确实没法得到包含数据行的JSON对象,因为它本质上是一个只读、单向的数据流,不是可直接被JSON序列化器识别的对象集合。你之前得到纯文本的原因,大概率是尝试直接把SqlDataReader实例传给了序列化方法,而序列化器只能读取它的元数据(比如是否关闭、字段数等),而非实际的行数据。
下面给你两种靠谱的解决方案,补全你的代码:
方法1:转换为DataTable后序列化
这是最直接的方式,把SqlDataReader的数据加载到DataTable中,再序列化整个DataTable:
using Newtonsoft.Json; // 如果你用Newtonsoft.Json,需要先安装NuGet包 // 或者用.NET Core/.NET 5+自带的System.Text.Json: using System.Text.Json; public JsonResult Teste() { using (SqlConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["Conexao"].ConnectionString)) { db.Open(); using (SqlCommand comando = new SqlCommand("select * from USERS", db)) { using (SqlDataReader reader = comando.ExecuteReader()) { DataTable dataTable = new DataTable(); dataTable.Load(reader); // 把reader的数据加载到DataTable // 序列化DataTable为JSON字符串 string json = JsonConvert.SerializeObject(dataTable); // 如果用System.Text.Json: string json = JsonSerializer.Serialize(dataTable); return Json(json, JsonRequestBehavior.AllowGet); // 或者在ASP.NET Core中直接返回: return Content(json, "application/json"); } } } }
方法2:手动读取行到动态对象/实体类列表
如果不想用DataTable(比如追求更好的性能或类型安全),可以逐行读取数据,存入List<dynamic>或者自定义的User实体类中,再序列化这个列表:
用动态对象的示例:
public JsonResult Teste() { List<dynamic> users = new List<dynamic>(); using (SqlConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["Conexao"].ConnectionString)) { db.Open(); using (SqlCommand comando = new SqlCommand("select * from USERS", db)) { using (SqlDataReader reader = comando.ExecuteReader()) { while (reader.Read()) { var user = new ExpandoObject(); var userDict = (IDictionary<string, object>)user; // 遍历所有列,把列名和对应值存入动态对象 for (int i = 0; i < reader.FieldCount; i++) { userDict.Add(reader.GetName(i), reader.IsDBNull(i) ? null : reader[i]); } users.Add(user); } } } } string json = JsonConvert.SerializeObject(users); return Json(json, JsonRequestBehavior.AllowGet); }
用自定义实体类的示例(更推荐,类型安全):
先定义User类:
public class User { public int Id { get; set; } public string Username { get; set; } public string Email { get; set; } // 根据你的USERS表字段添加对应的属性 }
然后修改读取逻辑:
public JsonResult Teste() { List<User> users = new List<User>(); using (SqlConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["Conexao"].ConnectionString)) { db.Open(); using (SqlCommand comando = new SqlCommand("select Id, Username, Email from USERS", db)) { using (SqlDataReader reader = comando.ExecuteReader()) { while (reader.Read()) { User user = new User { Id = reader.GetInt32(reader.GetOrdinal("Id")), Username = reader.GetString(reader.GetOrdinal("Username")), Email = reader.IsDBNull(reader.GetOrdinal("Email")) ? null : reader.GetString(reader.GetOrdinal("Email")) }; users.Add(user); } } } } string json = JsonConvert.SerializeObject(users); return Json(json, JsonRequestBehavior.AllowGet); }
注意事项
- 如果你使用的是ASP.NET Core,
JsonRequestBehavior.AllowGet已经不需要了,直接返回Json(users)即可,框架会自动处理序列化。 - 记得处理
DBNull的情况,避免序列化时出现异常。 - 如果用
System.Text.Json,需要注意一些序列化配置(比如处理空值、 camelCase命名等),可以通过JsonSerializerOptions调整。
内容的提问来源于stack exchange,提问作者Tiedt Tech
相关产品推荐
相关产品推荐

