下面的介紹,是我從《百度百科》中搬運過來。詳細的JSON改變你們能夠自行查閱編程
具體的連接地址,我就不放了。(放的話,會被認爲是廣告)json
該類所屬程序集:ide
System.Web.Extensions
使用時須要添加引用:測試
using System.Web.Script.Serialization;
1.序列化實例this
public class Student { public string ID { get; set; } public string Name { get; set; } public Student() { } public Student(string id, string name) { ID = id; Name = name; } } static void Main(string[] args) { Student student = new Student("stu1","stuName"); //序列化爲JSON JavaScriptSerializer js = new JavaScriptSerializer(); string stuJSON = js.Serialize(student); Console.WriteLine("序列化JSON字符串爲:{0}", stuJSON); //反序列化爲T Student stu1 = js.Deserialize<Student>(stuJSON); Console.WriteLine("ID:{0};Name:{1}", stu1.ID, stu1.Name); }
2.序列化集合lua
List<Student> lists = new List<Student>() { new Student("1","stu1"), new Student("2","stu2"), new Student("3","stu3") }; JavaScriptSerializer js = new JavaScriptSerializer(); //序列化 string serString = js.Serialize(lists); Console.WriteLine(serString); //反序列化 List<Student> desList = js.Deserialize<List<Student>>(serString); foreach (Student stu in desList) { Console.WriteLine("ID:{0},Name:{1}", stu.ID, stu.Name); }
3.使屬性不參與序列化spa
public class Student { public string ID { get; set; } public string Name { get; set; } //使用該特性,使得Birth不參與序列化 [ScriptIgnore] public DateTime Birth { get; set; } public Student() { } public Student(string id, string name, DateTime birth) { ID = id; Name = name; Birth = birth; } } static void Main(string[] args) { Student stu = new Student("1", "stu1", DateTime.Now.AddYears(-10)); JavaScriptSerializer js = new JavaScriptSerializer(); //序列化 string json = js.Serialize(stu); Console.WriteLine("序列化字符串:{0}", json); Console.WriteLine(""); //反序列化 Console.WriteLine("反序列化"); Student stuDes = js.Deserialize<Student>(json); Console.WriteLine("ID:{0},Name:{1}", stu.ID, stu.Name); }
運行結果code
從截圖能夠看出,Birth沒有參與序列化。orm
不少時候咱們的數據源不是集合,而是DataTable。此時若是咱們直接對其進行序列化,就會拋出循環引用的異常。blog
下面是MSDN的介紹
個人猜想是DataTable中的DataRow引用了DataTable(DataRow.Table)從而使得DataTable與DataRow之間循環引用了。
下面是解決序列化DataTable的三種方法,2個擴展方法,1個擴展類
2個擴展方法
public static class JSONHelper { /// <summary> /// 將DataTable轉換爲List /// </summary> /// <typeparam name="T">轉換的類型</typeparam> /// <param name="dataSource">數據源</param> /// <returns>轉換獲得的List</returns> public static List<T> ToList<T>(this DataTable dataSource) where T : class,new() { Type type = typeof(T); PropertyInfo[] propertyInfos = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); //返回集合 List<T> list = new List<T>(); foreach (DataRow row in dataSource.Rows) { T t = new T(); //循環屬性 foreach (PropertyInfo proInfo in propertyInfos) { //經過屬性名,獲得DataRow數據 if (row[proInfo.Name] != null) { //屬性賦值 proInfo.SetValue(t, row[proInfo.Name]); } } list.Add(t); } return list; } /// <summary> /// 將DataTable轉換爲List(js解析時使用) /// </summary> /// <param name="dataSource">數據源</param> /// <returns></returns> public static List<Dictionary<string, object>> ToList(this DataTable dataSource) { //集合 List<Dictionary<string, object>> list = new List<Dictionary<string, object>>(); foreach (DataRow row in dataSource.Rows) { //實體類 Dictionary<string, object> instance = new Dictionary<string, object>(); foreach (DataColumn col in dataSource.Columns) { //屬性 instance.Add(col.ColumnName, row[col.ColumnName]); } list.Add(instance); } return list; } } static void Main(string[] args) { DataTable table = new DataTable(); DataColumn[] cols = new DataColumn[] { new DataColumn("ID", typeof(string)), new DataColumn("Name", typeof(string)), new DataColumn("Birth", typeof(DateTime)) }; table.Columns.AddRange(cols); for (int i = 0; i < 3; i++) { DataRow row = table.NewRow(); row["ID"] = (i + 1).ToString(); row["Name"] = "stu" + i.ToString(); row["Birth"] = DateTime.Now.AddYears(-10).AddDays(i); table.Rows.Add(row); } JavaScriptSerializer js = new JavaScriptSerializer(); string json = string.Empty; #region 擴展方法一 //序列化 Console.WriteLine("擴展方法一"); json = js.Serialize(table.ToList<Student>()); Console.WriteLine(json); Console.WriteLine("\r\n"); //反序列化 List<Student> students = js.Deserialize<List<Student>>(json); foreach (Student stu in students) { Console.WriteLine("ID:{0};Name:{1}", stu.ID, stu.Name); } #endregion Console.WriteLine("\r\n"); #region 擴展方法二 Console.WriteLine("擴展方法二"); json = js.Serialize(table.ToList()); Console.WriteLine(json); #endregion }
1個擴展類
class DataTableConverter : JavaScriptConverter { /// <summary> /// 序列化 /// </summary> /// <param name="obj">須要序列化的數據</param> /// <param name="serializer">序列化操做類</param> /// <returns></returns> public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) { //須要序列化的數據 DataTable table = obj as DataTable; Dictionary<string, object> result = new Dictionary<string, object>(); result["table"] = table.ToList(); return result; } /// <summary> /// 反序列化 /// </summary> /// <param name="dictionary">反序列化的數據</param> /// <param name="type">反序列化數據的類型</param> /// <param name="serializer">序列化操做類</param> /// <returns></returns> public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) { if (dictionary == null) throw new ArgumentNullException("dictionary"); if (type == typeof(DataTable)) { foreach (KeyValuePair<string, object> table in dictionary) { //表名 DataTable dt = new DataTable(table.Key); //集合 List<Dictionary<string, object>> list = serializer.ConvertToType<List<Dictionary<string, object>>>(table.Value); //類 Dictionary<string, object> instance = list[0]; //列名 foreach (KeyValuePair<string, object> column in instance) { dt.Columns.Add(column.Key); } //賦值 foreach (Dictionary<string, object> dicItem in list) { DataRow row = dt.NewRow(); foreach (KeyValuePair<string, object> property in dicItem) { row[property.Key] = property.Value; } dt.Rows.Add(row); } return dt; } } return null; } /// <summary> /// 獲取本轉換器支持的類型 /// </summary> public override IEnumerable<Type> SupportedTypes { get { return new Type[] { typeof(DataTable) }; } } } static void Main(string[] args) { DataTable table = new DataTable(); DataColumn[] cols = new DataColumn[] { new DataColumn("ID", typeof(string)), new DataColumn("Name", typeof(string)) }; table.Columns.AddRange(cols); for (int i = 0; i < 3; i++) { DataRow row = table.NewRow(); row["ID"] = (i + 1).ToString(); row["Name"] = "stu" + i.ToString(); table.Rows.Add(row); } JavaScriptSerializer js = new JavaScriptSerializer(); //序列化 //講自定義類型註冊到轉換器中 js.RegisterConverters(new JavaScriptConverter[] { new DataTableConverter() }); string json = js.Serialize(table); Console.WriteLine(json); Console.WriteLine("\r\n"); //反序列化 DataTable desTable = js.Deserialize<DataTable>(json); foreach (DataRow row in desTable.Rows) { Console.WriteLine("ID:{0},Name:{1}", row["ID"], row["Name"]); } }
擴展類,須要繼承抽象類:JavaScriptConverter。
重寫2個抽象方法
IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
這裏重寫Serialize方法,我直接調用了以前寫好的JSONHelper中的方法。將DataTable轉換成了List<Dictionary<string,object>>。而後在重寫Deserialize時,就要根據Serialize序列化的類型,來獲取數據。在代碼中有體現。
1個抽象屬性
IEnumerable<Type> SupportedTypes{get;}
在調用時,須要將自定義的類型註冊到JavaScriptSerializer中。
該類所屬程序集:
System.Runtime.Serialization
使用時須要添加引用:
System.Runtime.Serialization.Json
須要參與序列化的類須要加上特性:[DataContract],須要參與序列化屬性須要加上特性:[DataMember]。
[DataMember(Name="xxx",Order=1)]能夠經過Name來指定序列化屬性的名稱,Order來指定序列化屬性的順序
因爲後面介紹複雜的序列化時,須要用到下面的測試代碼。因此這裏我就所有貼出了。
/// <summary> /// 表單信息 /// </summary> [DataContract] public class Form { /// <summary> /// 版本號 /// </summary> [DataMember(Name = "version", Order = 1)] public string Version { get; set; } /// <summary> /// 標題 /// </summary> [DataMember(Name = "title", Order = 2)] public string Title { get; set; } /// <summary> /// 表單域集合 /// </summary> [DataMember(Name = "fields", Order = 3)] public List<Field> Fields { get; set; } public Form() { Version = string.Empty; Title = string.Empty; Fields = new List<Field>(); } } /// <summary> /// 表單域 /// </summary> [DataContract] public abstract class Field { /// <summary> /// 區域名 /// </summary> [DataMember(Name = "name", Order = 1)] public string Name { get; set; } } /// <summary> /// 標題區域(head區域) /// </summary> [DataContract] public class HeadField : Field { /// <summary> /// 詳情 /// </summary> [DataMember(Name = "entrydata", Order = 1)] public List<HeadFieldData> EntryData { get; set; } public HeadField() { this.Name = string.Empty; EntryData = new List<HeadFieldData>(); } } /// <summary> /// 標題區域數據(head區域數據) /// </summary> [DataContract] public class HeadFieldData { /// <summary> /// 名稱 /// </summary> [DataMember(Name = "leftfield", Order = 1)] public string LeftField { get; set; } /// <summary> /// 值 /// </summary> [DataMember(Name = "rightfield", Order = 2)] public string RightField { get; set; } }
下面的代碼是JSONHelper幫助類
public class JsonHelper { /// <summary> /// JSON序列化 /// </summary> /// <typeparam name="T">序列化的類型</typeparam> /// <param name="t">序列化類型實例</param> /// <param name="knownTypes">擴充可序列化的類型(當面向接口編程時,須要使用)</param> /// <returns></returns> public static string JsonSerializer<T>(T t, IList<Type> knownTypes = null) { string jsonString = string.Empty; DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T), knownTypes, int.MaxValue, false, null, false); using (MemoryStream ms = new MemoryStream()) { ser.WriteObject(ms, t); jsonString = Encoding.UTF8.GetString(ms.ToArray()); } //替換掉"__type":"xxxxx", string matchingStr = "\"__type\":\"([^\"]+)\","; RegexOptions ops = RegexOptions.Multiline; Regex r = new Regex(matchingStr, ops); if (r.IsMatch(jsonString)) { jsonString = r.Replace(jsonString, ""); } //替換Json的Date字符串 string p = @"\\/Date\((\d+)\+\d+\)\\/"; MatchEvaluator matchEvaluator = new MatchEvaluator(ConvertJsonDateToDateString); Regex reg = new Regex(p); jsonString = reg.Replace(jsonString, matchEvaluator); return jsonString; } /// <summary> /// JSON反序列化 /// </summary> public static T JsonDeserialize<T>(string jsonString) { T obj = default(T); //將"yyyy-MM-dd HH:mm:ss"格式的字符串轉爲"\/Date(1294499956278+0800)\/"格式 string p = @"\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}"; MatchEvaluator matchEvaluator = new MatchEvaluator(ConvertDateStringToJsonDate); Regex reg = new Regex(p); jsonString = reg.Replace(jsonString, matchEvaluator); DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T)); using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString))) { obj = (T)ser.ReadObject(ms); } return obj; } /// <summary> /// 將Json序列化的時間由/Date(1294499956278+0800)轉爲字符串 /// </summary> private static string ConvertJsonDateToDateString(Match m) { string result = string.Empty; DateTime dt = new DateTime(1970, 1, 1); dt = dt.AddMilliseconds(long.Parse(m.Groups[1].Value)); dt = dt.ToLocalTime(); result = dt.ToString("yyyy-MM-dd HH:mm:ss"); return result; } /// <summary> /// 將時間字符串轉爲Json時間 /// </summary> private static string ConvertDateStringToJsonDate(Match m) { string result = string.Empty; DateTime dt = DateTime.Parse(m.Groups[0].Value); dt = dt.ToUniversalTime(); TimeSpan ts = dt - DateTime.Parse("1970-01-01"); result = string.Format("\\/Date({0}+0800)\\/", ts.TotalMilliseconds); return result; } }
JSONHelper中有一些正則,分別是處理多餘的"_type"節點與處理DateTime類型。
下面貼出使用DataContractJsonSerializer的測試代碼
static void Main() { string json = string.Empty; Form form = new Form(); form.Version = "1.0"; form.Title = "測試"; HeadField headField = new HeadField(); headField.Name = "測試頭數據"; HeadFieldData data1 = new HeadFieldData(); data1.LeftField = "數據1"; data1.RightField = "data1"; headField.EntryData.Add(data1); HeadFieldData data2 = new HeadFieldData(); data2.LeftField = "數據2"; data2.RightField = "data2"; headField.EntryData.Add(data2); HeadFieldData data3 = new HeadFieldData(); data3.LeftField = "數據3"; data3.RightField = "data3"; headField.EntryData.Add(data3); //頭信息添加入表單中 form.Fields.Add(headField); //IList<Type> knownTypes = new List<Type>() { typeof(HeadField) }; json = JSONHelper.JsonSerializer<Form>(form); Console.WriteLine(json); }
上面的代碼運行後會報錯
這段錯誤信息的意思,代碼JSONHelper.JsonSerializer<Form>(form);
只會將數據根據類Form進行序列化,可是Form中包含的HeadField,它不認識,因此報錯了。
解決這類問題,只須要將HeadField告訴DataContractJsonSerializer當遇到HeadField的數據時,就按照HeadField進行序列化。
IList<Type> knownTypes = new List<Type>() { typeof(HeadField) }; json = JSONHelper.JsonSerializer<Form>(form, knownTypes); Console.WriteLine(json);
只須要申明一個IList<Type>而後用typeof(HeadField)填充它,最後將IList<Type>傳遞給序列化的方法便可。
下面是正確的運行結果
感謝閱讀。