最近在学习ExtJs与ASP.NET结合开发,前者用到的数据内容基本上都是JSON格式,遂想写一个格式化数据成JSON的东东,在网上找了一下,发现还蛮多的,实现了一个类似于ToString()的方法,名曰:ToJson()。
不过在网上看到的基本上都是属于SCOTT大作的临摹版,90%以上都一样(我并不是说SCOTT大虾的杰作有什么不好,没有那个意思),于是我也照着葫芦画了一个瓢。废话就不多说了,直接进入正题。
先说说我的开发环境:
Windows Server 2008 DataCenter
Visual Studio 2008 Team System
SQL Server 2005 Developer(SQL 2008已经正式发布了,准备升级,^_^)
我照着SCOTT的大作(本文末有原著以及中文版链接)写了一个ToJson()出来。代码如下:
using System; using System.Web.Script.Serialization; namespace Demo { /// <summary> /// JSON帮助类 /// </summary> public static class JsonHelper { /// <summary> /// 格式化成Json字符串 /// </summary> /// <param name="obj">需要格式化的对象</param> /// <returns>Json字符串</returns> public static string ToJson(this object obj) { JavaScriptSerializer serializer = new JavaScriptSerializer(); return serializer.Serialize(obj); } /// <summary> /// 格式化成Json字符串 /// </summary> /// <param name="obj">需要格式化的对象</param> /// <param name="recursionDepth">指定序列化的深度</param> /// <returns>Json字符串</returns> public static string ToJson(this object obj, int recursionDepth) { JavaScriptSerializer serializer = new JavaScriptSerializer(); serializer.RecursionLimit = recursionDepth; return serializer.Serialize(obj); } } }
一字不漏的照打,应该没有问题吧(后来发现SCOTT大作末尾的Note,忘记看了,真是粗心啊~~~*_*)!
但是在编辑的时候,虽然是成功了,但是发现有2个警告,由于本人写程序一直都是尽自己最大努力来保证所写程序的警告数量最少,所以,当然要看看这两个警告到底是什么东东。
警告是:“System.Web.Script.Serialization.JavaScriptSerializer.JavaScriptSerializer()”已过时:“The recommended alternative is System.Runtime.Serialization.DataContractJsonSerializer.”
记得刚开始学习ASP.NET的时候,在用AppSettings的时候(具体哪个方法记不清了)也出现过类似的警告,最后是用ConfigurationManager代替就没有出现过该警告了,那这次应该也差不多吧。
于是到MSDN看看是怎么回事。没弄明白,再到CSDN看看呢。还是没弄明白,最后,求助一下Google。NND,折腾了半天,还是不知道到底是什么回事。
用“DataContractJsonSerializer”来代替吧,但是又少了对“System.Runtime.Serialization”的引用,把引用添加上吧,还是没有编译通过。
一直不知道是怎么回事,最后,幸运的Google到一个Demo,也是用“DataContractJsonSerializer”来代替上诉过时警告的。SCOTT大作中末尾Note给出的链接。
总算是明白怎么回事了。解决步骤如下:
首先,添加两个DLL的引用,分别是:System.Runtime.Serialization.dll、System.ServiceModel.Web.dll。
添加完引用之后,在cs代码页中添加using语句,如下:
using System; using System.IO; using System.Runtime.Serialization.Json;
注:因为要用到Stream等东东,所以这里要添加上System.IO这个命名空间。
总共三条using语句,在添加完之后,就可以开始写代码了,代码如下:
namespace Demo { /// <summary> /// JSON帮助类 /// </summary> public static class JsonHelper { /// <summary> /// 格式化成Json字符串 /// </summary> /// <param name="obj">需要格式化的对象</param> /// <returns>Json字符串</returns> public static string ToJson(this object obj) { // 首先,当然是JSON序列化 DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType()); // 定义一个stream用来存发序列化之后的内容 Stream stream = new MemoryStream(); serializer.WriteObject(stream, obj); // 从头到尾将stream读取成一个字符串形式的数据,并且返回 stream.Position = 0; StreamReader streamReader = new StreamReader(stream); return streamReader.ReadToEnd(); } } }
到此,该类的编写就完成了,剩下的就是调用了。
首先在Visual Studio 2008中新建一个库类项目(名称任意),将上述的内容添加到该项目中去,编译成一个dll文件供WebApplication(或WebSite)调用。我这里建的工程叫做Demo,编译出来的dll叫做Demo.dll。
然后在SQL Server 2005中新建一个数据库,在Web.config中配置好链接字符串,反正可以读取数据就行,这里就不再详述了。我这里建的数据库叫做Test,表名为Test_Table_01,字段有:TestID(int),Title(varchar(50)),Body(varchar(200)),Remark(varchar(200)),字段内添加了一些内容。
在Visual Studio 2008中新建一个WebApplication(也可以是WebSite),然后添加上述Demo.dll的引用,别慌,还需要添加“System.Runtime.Serialization”的引用,因为在后面添加实体层的时候,需要对实体层的属性进行序列化。我这里新建的是WebApplication,名称叫做Test。
然后在Test中添加了App_Code文件夹,在里面添加了一个类,叫做TestClass.cs。
该类就用于映射数据库Test中的表Test_Table_01,添加好cs文件之后,写入如下代码(C# 3.5的新特性^_^):
using System; using System.Runtime.Serialization; namespace Test { [DataContract] public class TestClass { [DataMember] public int TestID { get; set; } [DataMember] public string Title { get; set; } [DataMember] public string Body { get; set; } [DataMember] public string Remark { get; set; } } }
注:如果要对该类进行序列化,一定要在类前面添加上“[DataContract]”,在属性前面添加上“[DataMember]”,这样才能被“DataContractJsonSerializer”序列化成JSON。
在添加好TestClass.cs文件之后,在根目录新建一个Default.aspx页面,在页面中放一个Label,转到后台代码。
在cs代码上面添加“using Demo;”、“using System.Collections.Generic;”和“using System.Data.SqlClient;”这三条using语句。
然后新建一个方法,用于获取数据库中的数据,并且将获取出来的内容填入泛型中(这里给出的代码中,DataAccess是我自己根据SqlHelper重写的一个数据库访问类,其实直接用SqlHelper就可以了),代码如下:
// 获取表中的所有数据 private List<TestClass> GetAllData() { List<TestClass> list = new List<TestClass>(); string strSql = "SELECT * FROM Test_Table_01"; SqlCommand cmd = new SqlCommand(strSql); DataAccess da = new DataAccess(); try { SqlDataReader sdr = da.ExecuteReader(cmd); while (sdr.Read()) { list.Add(this.FillDetailWithReader(sdr)); } } finally { da.DisConnect(); } return list; } // 向泛型填充数据 private TestClass FillDetailWithReader(SqlDataReader reader) { TestClass model = new TestClass(); if (reader["TestID"] != DBNull.Value) model.TestID = (int)reader["TestID"]; if (reader["Title"] != DBNull.Value) model.Title = (string)reader["Title"]; if (reader["Body"] != DBNull.Value) model.Body = (string)reader["Body"]; if (reader["Remark"] != DBNull.Value) model.Remark = (string)reader["Remark"]; return model; }
这两个方法写好之后,就可以调用了。在Page_Load事件里面输入以下代码:
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // 首先调用GetAllData()方法获取数据库中的数据 List<TestClass> list = this.GetAllData(); // 将泛型list格式化成JSON字符串,并且赋值到Label1中去 Label1.Text = list.ToJson(); } }
到此,就完成了从SQL Server中读取数据、格式化成JSON字符串、并且输入的过程。
如今网上有很多这方面的内容,比如什么用LINQ读取啊,或者不用SQL Server,用XML等等,就靠大家自己去摸索的。
下一步目标:不知道大家注意到没有,上面SCOTT大作里面对ToJson()进行了重载,而我写的ToJson()方法只有一个,少了一个重载,这个就是我的下一步目标,希望是在没有警告的情况下,将序列化深度的自定义研究出来。