使用jquery将DataTable传递给Json

我正在尝试执行一个Web服务,该服务使用以下代码返回DataTable:

$.ajax({ type: "POST", url: url, data: data, contentType: "application/json; charset=utf-8", dataType: "json", success: function(msg) { //do things } }); 

如果webservice返回一个类,那么它就可以工作,因此它与输入参数等无关。它只在web方法返回一个数据表时失败(数据表只有2列和2行用于我正在进行的测试)。

WebService类使用[ScriptService]属性进行修饰,因此我认为ASP.NET会自动将返回值序列化为JSON。 它似乎不适用于数据表。

我发现的唯一解决方案是返回一个字符串(一个手动JSON序列化对象),但这样做对我来说似乎不对。
我正在使用Visual Studio 2008和.Net 3.5

最后,我决定使用JavaScriptSerializer类将DataTable转换为JSON字符串。 不幸的是,这个类不适用于DataTable,因此我将DataTable转换为dictionnaries列表并将该列表传递给JavaScriptSerializer类。 它只需几行代码,它工作正常。
VB.net中的示例:

  Public Function GetJson(ByVal dt As DataTable) As String Dim serializer As System.Web.Script.Serialization.JavaScriptSerializer = New System.Web.Script.Serialization.JavaScriptSerializer() Dim rows As New List(Of Dictionary(Of String, Object)) Dim row As Dictionary(Of String, Object) For Each dr As DataRow In dt.Rows row = New Dictionary(Of String, Object) For Each col As DataColumn In dt.Columns row.Add(col.ColumnName, dr(col)) Next rows.Add(row) Next Return serializer.Serialize(rows) End Function 

最简单的方法是使用LINQ to DataSet扩展。 首先需要使用LINQ to DataSet从DataTable创建一个通用列表(在这种情况下,SearchSerialResults只是一个DTO)。

  var resultItems = (from DataRow dr in _returnedData.AsEnumerable() select new SearchSerialResults { ContractLineItem = (int)dr["fldContractLineItemID"], SearchItem = (string)dr["Search Item"], Customer = (string)dr["Customer"], DeviceFound = (string)dr["Device Found"], Country = (string)dr["Country"], City = (string)dr["City"], ContractNumber = (string)dr["Contract Number"], QuoteNumber = (string)dr["Quote Number"], BeginDate = (string)dr["Begin Date"], EndDate = (string)dr["End Date"] }).ToList(); 

在这种情况下,_returnedData是DataTable。 第2步是进行转换。 在这种情况下,我正在为jqGrid返回一个Json对象。

 var jsonObject = new { total = totalPages, pageSize, records = totalRecords, rows = (from SearchSerialResults item in resultItems select new { id = item.ContractLineItem, cell = new[] { item.ContractLineItem.ToString(), item.SearchItem, item.DeviceFound, item.Customer, item.ContractNumber, item.QuoteNumber, item.Country, item.City, item.BeginDate, item.EndDate, "" } }).ToArray() }; return Json(jsonObject) // for MVC 

对于使用WebService的我来说,它非常适用

  Imports System.Web.Script.Serialization Dim wsServicio As New ["YourWsInstance"] Dim dsInstEstado As New DataSet Dim sSql As String sSql = " Your SQL Statement" dsInstEstado = wsServicio.getData("YourWebServiceParameters") Dim jsonString = DataTableToJSON(dsInstEstado.Tables("CA_INSTITUCION")) Return Json(jsonString, JsonRequestBehavior.AllowGet) Function DataTableToJSon(dt As DataTable) As Object Dim arr(dt.Rows.Count - 1) As Object Dim column As DataColumn For i = 0 To dt.Rows.Count - 1 Dim dict As New Dictionary(Of String, Object) For Each column In dt.Columns dict.Add(column.ColumnName, dt.Rows(i)(column)) Next arr(i) = dict Next Return arr End Function 

我必须承认我并不是非常惊讶 – DataTable基本上打破了结构化数据的大部分规则。 为什么不简单地从数据表投射到类型化对象? 之前提出了一个相关的问题 ……或者如果您知道DataTable的架构,只需在C#中进行转换……

手动构建JSON可能会起作用,但是有很多边缘情况需要避免; 说实话,我宁愿让现有的框架来处理它。

.Net 3.5有一个JSONSerializer,应该能够处理数据表。 您可能希望再次查看服务代码并尝试使用它。 此外,我将一些代码放在一起,在这个问题中手动完成。

和Marc一样,DataTable打破你的webservice / json交换也不奇怪。 我也想赞同Json.NET。

但是如果你决定不使用它,你仍然不必手动构建json。 只需使用您需要的所有属性创建自己的精简自定义类,然后返回该类的数组。 您当然必须编写代码以将数据表“转换”为新类。 我知道,这可能是很多代码编写,但是它更容易出错,然后尝试手动创建一个json字符串。

我发现这个C#类非常有用:

 [Serializable] public class TableMethod { private int m_total; public int total { get { return this.m_total; } set { this.m_total = value; } } private int m_page; public int page { get { return this.m_page; } set { this.m_page = value; } } private int m_records; public int records { get { return this.m_records; } set { this.m_records = value; } } private IList m_rows; public IList rows { get { return this.m_rows; } set { this.m_rows = value; } } public TableMethod() { this.m_records = 20; this.m_total = 20; this.m_page = 1; } } [Serializable] public class RowElement { public string id; public string[] cell; }