使用jQuery将DataTable转换为Json

6
我试图执行一个Web服务,该服务使用以下代码返回一个DataTable:
$.ajax({  
    type: "POST",  
    url: url,  
    data: data,   
    contentType: "application/json; charset=utf-8",  
    dataType: "json",  
    success: function(msg) {  
        //do things  
        }  
    }); 

如果Web服务返回一个类,那么它就可以正常工作,这与输入参数等无关。只有当Web方法返回一个数据表时才会失败(对于我正在测试的数据表,它只有2列和2行)。
WebService类使用[ScriptService]属性进行装饰,因此我认为ASP.NET会自动将返回值序列化为JSON。但似乎不能用于数据表。
我找到的唯一解决方案是返回一个字符串(手动JSON序列化对象),但我觉得这样做不太对。
我使用的是Visual Studio 2008和.Net 3.5。
9个回答

8
最终,我决定使用JavaScriptSerializer类将DataTable转换为JSON字符串。 不幸的是,此类无法处理DataTable,因此我将DataTable转换为字典列表,并将该列表传递给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

6
最简单的方法是使用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。第二步是进行转换。在这种情况下,我为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

1
我认为你的答案是最好的。 - Daniel B
一样。使用LINQ并获取你所需的内容。比手动循环遍历结果要简单得多。 - Jarrod Nettles
很棒的答案。这是其中一个“傻瓜”时刻,我简直不敢相信我竟然要查找这个。 - Bradley Mountford
顺便提一下,您不应该使用AsEnumerable扩展。这个也可以:var blah =(from DataRow dr in dataTable.Rows select new {prop1 =(string)dr [“someString”],prop2 =(int)dr [“someInt”]}); - Bradley Mountford


4
Json.NET有将DataSets/DataTables转换为JSON的能力。 这里是一个关于如何使用Json.NET序列化DataSets/DataTables的示例。

2

对我来说,使用 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

1

我必须承认,我并不感到非常惊讶 - DataTable 基本上违反了结构化数据的大部分规则。为什么不直接从数据表中投影到一个类型化的对象呢?之前出现过一个相关问题...或者如果你知道DataTable的模式,就在C#中进行转换...

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


0

.Net 3.5有一个JSONSerializer,应该能够处理datatable。您可能需要再次查看您的服务代码,并尝试让它使用该工具。此外,我还编写了一些手动代码,可以在this question.中找到。


0

像Marc一样,我也不惊讶DataTable会破坏你的webservice/json交换。我想背书Json.NET。

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


0
我发现这个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<RowElement> m_rows; public IList<RowElement> 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;
}

1
这里应该加上一些解释会更有帮助。 - Andrew Barber

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