【问题标题】:DataTable to JSON [duplicate]数据表转 JSON
【发布时间】:2010-10-01 21:00:54
【问题描述】:

我最近需要将数据表序列化为 JSON。我在哪里,我们仍然在 .Net 2.0 上,所以我不能在 .Net 3.5 中使用 JSON 序列化程序。我想这一定是以前做过的,所以我去网上找了foundnumberdifferentoptions。其中一些依赖于一个额外的库,我很难在这里推进。其他需要先转换为List<Dictionary<>>,这似乎有点尴尬和不必要。另一个将所有值视为字符串。出于某种原因,我无法真正落后于他们中的任何一个,所以我决定推出自己的,发布在下面。

从阅读//TODO cmets 可以看出,它在一些地方是不完整的。这段代码已经在这里生产了,所以它在基本意义上是“工作”的。它不完整的地方是我们知道我们的生产数据当前不会命中它的地方(数据库中没有时间跨度或字节数组)。我在这里发帖的原因是我觉得这可以更好一些,我希望帮助完成和改进这段代码。欢迎任何意见。

请注意,此功能内置于 .Net 3.5 及更高版本中,因此今天使用此代码的唯一原因是如果您仍受限于 .Net 2.0。即便如此,JSON.Net 已经成为这类事情的 goto 库。

public static class JSONHelper
{
    public static string FromDataTable(DataTable dt)
    {
        string rowDelimiter = "";

        StringBuilder result = new StringBuilder("[");
        foreach (DataRow row in dt.Rows)
        {
            result.Append(rowDelimiter);
            result.Append(FromDataRow(row));
            rowDelimiter = ",";
        }
        result.Append("]");

        return result.ToString();
    }

    public static string FromDataRow(DataRow row)
    {
        DataColumnCollection cols = row.Table.Columns;
        string colDelimiter = "";

        StringBuilder result = new StringBuilder("{");       
        for (int i = 0; i < cols.Count; i++)
        { // use index rather than foreach, so we can use the index for both the row and cols collection
            result.Append(colDelimiter).Append("\"")
                  .Append(cols[i].ColumnName).Append("\":")
                  .Append(JSONValueFromDataRowObject(row[i], cols[i].DataType));

            colDelimiter = ",";
        }
        result.Append("}");
        return result.ToString();
    }

    // possible types:
    // http://msdn.microsoft.com/en-us/library/system.data.datacolumn.datatype(VS.80).aspx
    private static Type[] numeric = new Type[] {typeof(byte), typeof(decimal), typeof(double), 
                                     typeof(Int16), typeof(Int32), typeof(SByte), typeof(Single),
                                     typeof(UInt16), typeof(UInt32), typeof(UInt64)};

    // I don't want to rebuild this value for every date cell in the table
    private static long EpochTicks = new DateTime(1970, 1, 1).Ticks;

    private static string JSONValueFromDataRowObject(object value, Type DataType)
    {
        // null
        if (value == DBNull.Value) return "null";

        // numeric
        if (Array.IndexOf(numeric, DataType) > -1)
            return value.ToString(); // TODO: eventually want to use a stricter format. Specifically: separate integral types from floating types and use the "R" (round-trip) format specifier

        // boolean
        if (DataType == typeof(bool))
            return ((bool)value) ? "true" : "false";

        // date -- see http://weblogs.asp.net/bleroy/archive/2008/01/18/dates-and-json.aspx
        if (DataType == typeof(DateTime))       
            return "\"\\/Date(" + new TimeSpan(((DateTime)value).ToUniversalTime().Ticks - EpochTicks).TotalMilliseconds.ToString() + ")\\/\"";

        // TODO: add Timespan support
        // TODO: add Byte[] support

        //TODO: this would be _much_ faster with a state machine
        //TODO: way to select between double or single quote literal encoding
        //TODO: account for database strings that may have single \r or \n line breaks
        // string/char  
        return "\"" + value.ToString().Replace(@"\", @"\\").Replace(Environment.NewLine, @"\n").Replace("\"", @"\""") + "\"";
    }
}

更新:
这已经过时了,但我想指出一些关于这段代码如何处理日期的事情。我当时使用的格式是有道理的,因为网址中有确切的理由。但是,该理由包括以下内容:

老实说,JSON Schema 确实通过将字符串“子类型化”为日期文字来解决问题,但这仍在进行中,需要一段时间才能实现任何重大采用。

嗯,时间已经过去了。今天,可以只使用ISO 8601 日期格式。我不会费心更改代码,因为真的:这是古老的。只需使用 JSON.Net。

【问题讨论】:

  • 如果今天问这个问题,它应该属于代码审查堆栈交换。我已将它标记为将其移到那里,但它引起我注意的唯一原因是它刚刚获得了“著名问题”金徽章。在迁移中失去该视图计数会很糟糕。
  • 我认为这太旧了,无法迁移。如果你同意的话,它可以在这里继续存在吗?
  • 我不介意任何一种方式,只是考虑最合适的方式。我还搬了其他旧东西。
  • 那里有很棒的代码。非常有帮助和直接。
  • 为什么这仍然获得投票? .Net 2 现在已经 8 岁了,以后的版本开箱即用转换为 json。 没有充分的理由再需要这样的东西了。另外,FWIW,我现在知道原始代码困扰我的是什么:我应该要求一个字符串作为传递给我的函数(或在构造函数中)的参数,并将我的 json 字符串写入该 straem 以让 asp .net 程序员传递 Response.Output 流。这应该大大提高性能/可扩展性。

标签: c# .net json .net-2.0 datatable


【解决方案1】:

嘿伙计,这一切都在 Rick 的博文Serializing DataTable using Json.NET 中。他详细解释了如何使用来自James Newton KingJson.NET 来完成它。

【讨论】:

  • 你不应该发布受linkrot约束的答案
【解决方案2】:

如果它是微软的AJAX extensions for .NET 2.0,它会帮助你说服你的老板安装一个库吗?

其中包含System.Web.Script.Serialization.JavascriptSerializer,用于您帖子中last link 的第4 步。

【讨论】:

  • 有没有办法在不安装额外库的情况下做到这一点?
【解决方案3】:

我发现了这个:http://www.bramstein.com/projects/xsltjson/ 您可以将数据表转换为 xml,并使用 xslt 样式表将 xml 转换为 json。

与其说是真正的解决方案,不如说是一种解决方法。

【讨论】:

  • 提个醒:我不知道这个投票有多低,但我没有对我的问题的善意答案投反对票的习惯。
猜你喜欢
  • 2017-01-24
  • 2012-08-12
  • 1970-01-01
  • 1970-01-01
  • 2016-04-27
  • 1970-01-01
  • 2023-04-11
  • 2017-05-13
相关资源
最近更新 更多