代码之家  ›  专栏  ›  技术社区  ›  Joel Coehoorn

JSON的数据表

  •  19
  • Joel Coehoorn  · 技术社区  · 16 年前

    我最近需要将数据表序列化为JSON。在我所在的位置,我们仍然在.NET 2.0上,所以我不能在.NET 3.5中使用JSON序列化程序。我想这一定是以前做过的,所以我上网查了一下 found number 属于 different options . 他们中的一些人依赖于一个额外的图书馆,我在这里很难找到。其他需要先转换为 List<Dictionary<>> 似乎有点尴尬和不必要。另一个将所有值都当作字符串处理。出于某种原因,我不能真正落后于他们中的任何一个,所以我决定滚动我自己的,这是张贴在下面。

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

    请注意,此功能内置于.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("\"", @"\""") + "\"";
        }
    }
    

    更新:
    这已经很旧了,但我想指出一些关于此代码如何处理日期的内容。我当时使用的格式很有意义,因为URL中有确切的理由。然而,这种理由包括:

    说实话,JSON模式确实解决了这个问题,它可以将字符串作为日期文本“子类型化”,但这仍然在进行中,而且在实现任何重要的采用之前都需要一些时间。

    好吧,时间过去了。今天,只使用 ISO 8601 日期格式。我不想费心修改代码,因为这真的很古老。只需使用json.net。

    3 回复  |  直到 11 年前
        1
  •  5
  •   Powerlord    16 年前

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

    其中包括: System.Web.Script.Serialization.JavascriptSerializer ,用于 last link 在你的岗位上。

        2
  •  1
  •   tuinstoel    16 年前

    我发现这一点: http://www.bramstein.com/projects/xsltjson/ 您可以将数据表转换为XML,并使用XSLT样式表将XML转换为JSON。

    与其说它是真正的解决方案,不如说它是一种权宜之计。

        3
  •  1
  •   Joel Coehoorn    16 年前

    嘿,布迪,这都在里克的博客里。 Serializing DataTable using Json.NET . 他详细解释了如何使用 Json.NET James Newton King .