【问题标题】:What's the best way to jSON serialize a .NET DataTable in WCF?在 WCF 中 JSON 序列化 .NET DataTable 的最佳方法是什么?
【发布时间】:2013-07-29 12:10:24
【问题描述】:

当我将 WCF 配置为使用 jSON 序列化并在我的一个 DataContract 中包含一个 DataTable 时,它​​会先将 DataTable 序列化为 XML,然后再将整个 DataContract 序列化为 JSON。我希望将 DataTable 序列化为 JSON,而不是 XML。

我的问题是:

  1. 为什么要先将DataTable序列化为XML?
  2. 如何让它序列化为 JSON?

【问题讨论】:

标签: .net json wcf serialization json.net


【解决方案1】:
  1. DataTable 是纯 .NET 构造,不能(轻松)以无损方式由 JSON 表示。 DataTables 包含许多 JSON 无法存储的附加信息:主键、autoincs、允许空值、标题、数据类型、索引等。序列化为 XML/Binary 是 DataTable 可以由 .NET 本机序列化的唯一方式。然后将此 XML 序列化的 DataTable 序列化为 JSON。

  2. 使用 JSON.NETFastJSON 将 DataTable 转换为普通、干净的与 JSON 兼容的 DataTable 版本,任何 JSON 客户端都可以使用该版本,而不仅仅是 .NET WCF 客户端。您将丢失上面 (1) 中提到的所有 DataTable 自定义属性,并且只会获取字段名称/值 JSON 对。由于每行中的字段名称重复,这种方式的存储效率很低。

不要在 DataContract 中使用 DataTable。如果您想要 DataTable 的好处并且您的客户端始终是 .NET,请通过 Binary Serialization 将 DataTable 序列化为字节数组,然后可选地压缩生成的序列化字节流。在 DataContract 中公开一个字节数组。这将为您提供客户端上高效、完全无损的 DataTable 版本(在解压缩和二进制反序列化之后),而不是简化的 JSON 版本的 DataTable(由 (2) 提供)...

【讨论】:

  • 很好的答案。谢谢你。我的客户并不都是 .NET,我很快就发现了你提到的低效率。我将尝试修改这种方法,这样我就不必在每一行中都包含列/字段名称。
  • 我知道这是一个旧线程,但是 fastjson 支持从 2011 年 6 月之前发布的 1.7.7 版本开始的数据表序列化/反序列化。并且 xml 格式效率低下,它包含每个字段的繁琐标签和行。
  • @Keith Blows,序列化数据表列表怎么样?你建议怎么做?
  • 我创建了this gist 来测试 Newtonsoft.Json(打算在 linqpad 中运行)。序列化按您希望的方式工作。
【解决方案2】:

试试这个:

public string ConvertDataTabletoString(System.Data.DataTable dt)
{
    System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
    List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();
    Dictionary<string, object> row;
    foreach (System.Data.DataRow dr in dt.Rows)
    {
        row = new Dictionary<string, object>();
        foreach (System.Data.DataColumn col in dt.Columns)
        {
            row.Add(col.ColumnName, dr[col]);
        }
        rows.Add(row);
    }
    return serializer.Serialize(rows);
}

【讨论】:

    【解决方案3】:

    我有同样的问题,我的 wcf 服务在将它从 Dataset 转换为 Json 时没有正确格式化 json。 我使用以下解决方案让它工作:

    using System.ServiceModel.Channels;
    using System.ServiceModel.Web;
    

    dsData 是我的数据集

    string json = Newtonsoft.Json.JsonConvert.SerializeObject(dsData);
    return WebOperationContext.Current.CreateTextResponse(json, "application/json;charset=utf-8", System.Text.Encoding.UTF8);
    

    并且“消息”将是返回类型。

    【讨论】:

    • 这个答案今天真的救了我的命 :) 我放弃了寻找简单的方法将 DataTable 从 db 返回到 JSON 而不为每个表/过程显式声明对象。我的错误是我的OperationContract 将序列化的 json 简单地作为string 返回。这样,它需要,例如,使用JSON.parse 客户端。将返回类型更改为System.ServiceModel.Channels.Message 并使用WebOperationContext.Current.CreateTextResponse(string),如上所示完美运行! :)
    • 我从来没有真正想过你可以用 WCF WS 做这样的事情——设置响应而不是仅仅返回 int/string/class/List&lt;T&gt; etc
    【解决方案4】:

    根据其主页上的图表,Json.NET 确实是您唯一的选择 - 您可以从NuGet 快速获取它。幸运的是,它是一个很棒的库,而且非常易于使用。

    string json = JsonConvert.SerializeObject(myDataSet, new DataSetConverter());
    

    请注意,Rich Strahl 有一篇很棒的帖子,其中包含更多详细信息,并且为了比较,他还包含了一些他使用 JavaScriptSerializer 和(相当广泛的)自定义转换器所做的自定义工作。

    【讨论】:

    • 这行得通,但后来我很快意识到每一行都包含数据列/字段名称,这使得它非常低效,正如 Keith 所说。我将尝试修改 DataTableConverter 和 DataRowConverter,以免重复所有这些列/字段名称。
    • @rhyno 不重复所有列/字段名称的最终解决方案是什么?我知道我要做什么,但如果你已经完成了,那会节省我一些时间。
    猜你喜欢
    • 1970-01-01
    • 2010-10-03
    • 2015-01-29
    • 1970-01-01
    • 1970-01-01
    • 2012-10-30
    • 2014-01-20
    • 2021-10-24
    • 2010-09-27
    相关资源
    最近更新 更多