C#中JSON反序列化为DataSet的新方法及报错解决方案咨询
解决JSON反序列化为DataSet及Excel/PDF导出兼容IE的问题
咱们先一步步拆解你的问题,先把两个报错的根源搞定,再落实到导出需求的解决方案~
一、报错原因分析
你的两个报错本质上是同一个问题:JSON格式不标准!
- 自定义
JsonStringToDataTable报错:你的JSON里的键(比如Vehicle、Date)没有用双引号包裹,导致正则拆分逻辑找不到预期的逗号位置,直接抛出解析列名的异常。 - Newtonsoft.Json报错:Newtonsoft严格遵循JSON规范,要求对象的键必须用双引号包裹,遇到未加引号的
Vehicle就直接触发格式错误。
二、第一步:修正JSON格式(关键!)
不管是手动拼接还是前端Ajax发送,都要确保生成标准JSON——键和字符串值必须用双引号包裹。比如你的示例JSON要改成:
"[{\"Vehicle\":\"BMW With Ethiraj\",\"Date\":\"30 Jul 2013 09:24 AM\",\"Location\":\"Hauz Khas Enclave New Delhi Delhi India\", \"Speed\":\"42\"}]"
更推荐的做法是在前端用JSON.stringify()自动序列化对象,避免手动拼接出错:
// 前端JQuery Ajax代码示例 var vehicleList = [{ Vehicle: "BMW With Ethiraj", Date: "30 Jul 2013 09:24 AM", Location: "Hauz Khas Enclave New Delhi Delhi India", Speed: 42 }]; $.ajax({ url: "YourWebForm.aspx/ExportVehicleData", type: "POST", contentType: "application/json; charset=utf-8", // 必须设置这个 data: JSON.stringify({ vehicleData: vehicleList }), // 用JSON.stringify序列化 success: function(res) { // 若后端直接输出文件,这里无需额外处理,浏览器会自动触发下载 } });
三、正确反序列化为DataSet/DataTable
放弃你那个依赖正则的自定义方法(太脆弱,容易因为格式小变动报错),用Newtonsoft.Json(也就是Json.NET)的官方方法,简单又可靠:
1. 直接反序列化为DataTable
如果你的JSON是单表数组格式,直接转成DataTable,再加入DataSet即可:
using Newtonsoft.Json; // 假设webmethod接收的是标准JSON字符串 [WebMethod] public static void ExportToExcel(string jsonData) { // 反序列化为DataTable DataTable dt = JsonConvert.DeserializeObject<DataTable>(jsonData); // 转成DataSet DataSet ds = new DataSet(); ds.Tables.Add(dt); // 后续执行导出操作... }
2. 更安全的类型化接收(推荐)
直接在WebMethod里接收强类型集合,再转成DataTable,避免JSON格式问题:
// 先定义实体类,对应你的数据结构 public class VehicleInfo { public string Vehicle { get; set; } public string Date { get; set; } public string Location { get; set; } public int Speed { get; set; } } [WebMethod] public static void ExportVehicleData(List<VehicleInfo> vehicleData) { // 把List转成DataTable(辅助方法见下方) DataTable dt = ConvertListToDataTable(vehicleData); DataSet ds = new DataSet(); ds.Tables.Add(dt); // 执行导出... } // 辅助方法:将强类型List转为DataTable private static DataTable ConvertListToDataTable<T>(List<T> dataList) { System.ComponentModel.PropertyDescriptorCollection props = System.ComponentModel.TypeDescriptor.GetProperties(typeof(T)); DataTable dt = new DataTable(); // 添加列 foreach (System.ComponentModel.PropertyDescriptor prop in props) { dt.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType); } // 添加数据行 foreach (T item in dataList) { DataRow row = dt.NewRow(); foreach (System.ComponentModel.PropertyDescriptor prop in props) { row[prop.Name] = prop.GetValue(item) ?? DBNull.Value; } dt.Rows.Add(row); } return dt; }
四、Excel/PDF导出(兼容IE的后端方案)
前端导出不兼容IE,后端生成文件并通过Response输出是最优解,这里给你两种常用实现:
1. Excel导出(用EPPlus,轻量无需Office)
先在NuGet安装EPPlus包,然后写导出逻辑:
using OfficeOpenXml; [WebMethod] public static void ExportToExcel(List<VehicleInfo> vehicleData) { DataTable dt = ConvertListToDataTable(vehicleData); // 创建Excel包 using (ExcelPackage excelPackage = new ExcelPackage()) { ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets.Add("车辆数据"); // 直接从DataTable加载数据(自动生成表头) worksheet.Cells["A1"].LoadFromDataTable(dt, true); // 设置响应头,触发浏览器下载 HttpContext.Current.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=VehicleReport.xlsx"); HttpContext.Current.Response.BinaryWrite(excelPackage.GetAsByteArray()); HttpContext.Current.Response.End(); } }
2. PDF导出(用iTextSharp)
先在NuGet安装iTextSharp包,实现导出:
using iTextSharp.text; using iTextSharp.text.pdf; using System.IO; [WebMethod] public static void ExportToPdf(List<VehicleInfo> vehicleData) { DataTable dt = ConvertListToDataTable(vehicleData); Document pdfDoc = new Document(PageSize.A4, 10, 10, 10, 10); MemoryStream ms = new MemoryStream(); PdfWriter.GetInstance(pdfDoc, ms); pdfDoc.Open(); // 创建PDF表格 PdfPTable pdfTable = new PdfPTable(dt.Columns.Count); pdfTable.WidthPercentage = 100; // 添加表头 foreach (DataColumn col in dt.Columns) { pdfTable.AddCell(new Phrase(col.ColumnName, new Font(Font.FontFamily.HELVETICA, 12, Font.BOLD))); } // 添加数据行 foreach (DataRow row in dt.Rows) { foreach (var cellValue in row.ItemArray) { pdfTable.AddCell(new Phrase(cellValue.ToString())); } } pdfDoc.Add(pdfTable); pdfDoc.Close(); // 输出到浏览器 HttpContext.Current.Response.ContentType = "application/pdf"; HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=VehicleReport.pdf"); HttpContext.Current.Response.BinaryWrite(ms.ToArray()); HttpContext.Current.Response.End(); }
五、注意事项
- 前端Ajax必须设置
contentType: "application/json; charset=utf-8",否则后端WebMethod无法正确解析JSON参数。 - 若使用EPPlus,注意版本兼容性(最新版需配置
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;)。 - IE对文件下载的响应头兼容性较好,只要正确设置
Content-Type和Content-Disposition即可触发下载。
内容的提问来源于stack exchange,提问作者ethiraj
相关产品推荐
相关产品推荐

