You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:10:22