[.net 物件導向程式設計進階] (13) 序列化(Serialization)(五) Json 序列化利器 Newtonsoft.Json 及 通用Json類
本節導讀:
關於JSON序列化,不能不瞭解Json.net(Newtonsoft.Json)這款世界級的開源類庫,除了擁有良好的效能之外,功能也是非常強大的。
本節會詳細說明這個類庫。此外,對於不喜歡使用第三方類庫的同學,會整理一個基於微軟類庫的通用Json類。
讀前必備:
本節主要介紹一款第三方類庫和一個自己整理封裝的類庫,說起到封裝就想到.NET物件導向三大特性。有需要的朋友可以參考下面三篇。
A.封裝 [.net 物件導向程式設計基礎] (11) 物件導向三大特性——封裝
B.繼承 [.net 物件導向程式設計基礎] (12) 物件導向三大特性——繼承
C.多型 [.net 物件導向程式設計基礎] (13) 物件導向三大特性——多型
1. 第三方類庫Newtonsoft.Json
1.1 和.NET自帶類庫比較
目前使用的三種JSON序列化和類庫主要有:
A. DataContractJsonSerializer (微軟自帶類庫)
B. JavaScriptSerializer (微軟自帶類庫)
C.Json.net 即Newtonsoft.Json (第三方開源Json型別)
就效能而言,DataContractJsonSerializer 和 Newtonsoft.Json差距不大,JavaScriptSerializer 效能略差一些。
下圖是一張來自Newtonsoft.net官方的效能測試圖表。
功能方面,當然不用說Newtonsoft.net是專家做Json的開源庫,自然功能強大一些。下面會將Newtonsoft.net一些比較實用的功能介紹一下。
1.2 Newtonsoft.net簡介
最新版本:7.01 截止我釋出本篇文章時
官方地址:https://github.com/JamesNK/Newtonsoft.Json/releases
我提供一個下載:http://files.cnblogs.com/files/yubinfeng/Newtonsoft.Json7.0.1-.net4.0.rar
在打包的時候,為每個版本的.net都有一個dll,這上傳是即於最高版本.net4.0版本的。
官方提供的下載在國內真是相當的慢。
1.3 常用序列化DataTable、DataSet、Entity
三個使用方法都相似,我以DataSet為例介紹:
使用前在專案中引用,這個就不用多說了
//建立 DataTable 1 DataTable dt1 = new DataTable("Top") ; dt1.Columns.AddRange(new DataColumn[]{ new DataColumn { ColumnName = "Name", DataType = typeof(System.String) }, new DataColumn { ColumnName = "Age", DataType = typeof(System.Int32) }, new DataColumn { ColumnName = "MenPai", DataType = typeof(System.String) } }); dt1.Rows.Add(new object[]{"周伯通", 22,"重陽宮" }); dt1.Rows.Add(new object[]{"洪七公", 19,"丐幫" }); dt1.Rows.Add(new object[]{"黃藥師",55,"桃花島" }); dt1.Rows.Add(new object[]{"歐陽鋒",49,"白駝山" }); //建立 DataTable 2 DataTable dt2 = dt1.Clone(); dt2.TableName = "Second"; dt2.Rows.Add(new object[]{"郭靖",22,"丐幫"}); dt2.Rows.Add(new object[]{"黃蓉",19,"丐幫"}); dt2.Rows.Add(new object[]{ "梅超風", 55,"桃花島"}); dt2.Rows.Add(new object[]{ "楊康", 49,"金"}); //建立DataSet DataSet ds = new DataSet("Master"); ds.Tables.AddRange(new DataTable[]{ dt1,dt2}); //序列化DataSet為Json字串 string myJsonStr = JsonConvert.SerializeObject(ds); Console.WriteLine(myJsonStr);
執行結果如下 :
下面將上面生成的字串myJsonStr反序列化為DataSet
//DataSet反序列化 DataSet newDs = JsonConvert.DeserializeObject<DataSet>(myJsonStr); foreach(DataTable Ds in newDs.Tables) { Console.WriteLine(Ds.TableName + "\n"); foreach (DataRow dr in Ds.Rows) { foreach (DataColumn dc in Ds.Columns) Console.Write(dc.ColumnName + ":"+dr[dc] +" "); Console.WriteLine("\n"); } }
執行結果如下:
1.4 Newtonsoft.net 特殊處理功能
上面的示例展示了 Newtonsoft.net基本序列化和反序列化,那麼能不能像DataContractJsonSerializerg 一樣只處理標記的實體類屬性或欄位呢,答案是肯定可以。在特殊處理能力上,Newtonsoft.net非常強大,下面舉例說明幾種:
A.設定序列化模式
序列化模式上有兩種:
OptOut:除外模式;預設表示序列化所有成員,如果某些成員不想序列化,在類成員上加上標記[JsonIgnore],當然類也要標記序列模式[JsonObject(MemberSerialization.OptOut)]
OptIn:包含模式; 預設表示不序列化所有成員,如果某些成員想序列化,可以在類成員上標記[JsonProperty],同樣的,需要在類上也標記序列模式 [JsonObject(MemberSerialization.OptIn)]
下面示例 說明:
先建立類“武林高手”
/// <summary> /// 類:武林高手 /// MartialArtsMaster /// </summary> [JsonObject(MemberSerialization.OptOut)] public class MartialArtsMaster { [JsonIgnore] /// <summary> /// 編號 /// </summary> public int id { get; set; } /// <summary> /// 姓名 /// </summary> public string name { get; set; } /// <summary> /// 門派 /// </summary> public string menpai { get; set; } [JsonIgnore] /// <summary> /// 武功 /// </summary> public string kongFu { get; set; } }
新增資料並序列化:
//增加幾個武林高手 List<MartialArtsMaster> masterList = new List<MartialArtsMaster>() { new MartialArtsMaster(){ id=1, name="段譽", menpai="天龍寺", kongFu="六脈神劍"}, new MartialArtsMaster(){ id=2, name="喬峰", menpai="丐幫", kongFu="降龍十八掌"}, new MartialArtsMaster(){ id=3, name="虛竹", menpai="逍遙派", kongFu="北冥神功"} }; //序列化DataSet為Json字串 string myJsonStr = JsonConvert.SerializeObject(masterList); Console.WriteLine(myJsonStr);
執行結果如下:
下面看一下包含模式(OptIn):
類及成員標識如下:
/// <summary> /// 類:武林高手 /// MartialArtsMaster /// </summary> [JsonObject(MemberSerialization.OptIn)] public class MartialArtsMaster { /// <summary> /// 編號 /// </summary> public int id { get; set; } [JsonProperty] /// <summary> /// 姓名 /// </summary> public string name { get; set; } [JsonProperty] /// <summary> /// 門派 /// </summary> public string menpai { get; set; } /// <summary> /// 武功 /// </summary> public string kongFu { get; set; } }
序列化:
//增加幾個武林高手 List<MartialArtsMaster> masterList = new List<MartialArtsMaster>() { new MartialArtsMaster(){ id=1, name="段譽", menpai="天龍寺", kongFu="六脈神劍"}, new MartialArtsMaster(){ id=2, name="喬峰", menpai="丐幫", kongFu="降龍十八掌"}, new MartialArtsMaster(){ id=3, name="虛竹", menpai="逍遙派", kongFu="北冥神功"} }; //序列化DataSet為Json字串 string myJsonStr = JsonConvert.SerializeObject(masterList); Console.WriteLine(myJsonStr);
執行結果如果如下:
B.處理預設值
類庫對實體帶預設值的成員是否序列化?情況有兩種處理機制:
序列化和反序列化時,忽略預設值 DefaultValueHandling.Ignore
序列化和反序列化時,包含預設值 DefaultValueHandling.Include
需要注意兩點:
一是,定義屬性預設值,需要引用名稱空間using System.ComponentModel;
二是,Formatting.Indented列舉表示輸出的JSON是有縮排處理。
C.處理空值
空值 使用 JsonSerializerSettings.NullValueHandling 設定
空值也是有兩個開關:
不序列空值 NullValueHandling.Ignore
序列化空值(預設)NullValueHandling.Include
//增加幾個武林高手 List<MartialArtsMaster> masterList = new List<MartialArtsMaster>() { new MartialArtsMaster(){ id=1, name="段譽", menpai="天龍寺"}, new MartialArtsMaster(){ id=2, name="喬峰", menpai="丐幫", kongFu="降龍十八掌"}, new MartialArtsMaster(){ id=3, name="虛竹", menpai="逍遙派", kongFu="北冥神功"} }; //設定預設處理項 JsonSerializerSettings jsonSettings = new JsonSerializerSettings(); jsonSettings.NullValueHandling = NullValueHandling.Ignore; //序列化DataSet為Json字串 string myJsonStr = JsonConvert.SerializeObject(masterList,Formatting.Indented,jsonSettings); Console.WriteLine(myJsonStr);
執行結果如下:
D.處理非公有成員
(這一點DataContractJsonSerializerg 只支援公有,而Newtonsoft.Json可以支援 序列化私有成員)
處理方法:只需要在私有成員上面加標識["JsonProperty"],就可以了。
[JsonProperty] private string gongFu{ get; set; }
E.處理日期
對於日期處理也是這套類庫比較強大的地方,提供了轉換類IsoDateTimeConverter來完成對日期的處理。
先定繼承兩個類,重寫來處理兩種日期格式,然後在實體類中標記
public class MyDateTimeConverter : DateTimeConverterBase { private static IsoDateTimeConverter dtConverter = new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd hh-mm-ss" }; public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { return dtConverter.ReadJson(reader, objectType, existingValue, serializer); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { dtConverter.WriteJson(writer, value, serializer); } } public class MyCnDateTimeConverter : DateTimeConverterBase { private static IsoDateTimeConverter dtConverter = new IsoDateTimeConverter { DateTimeFormat = "yyyy年MM月d日 hh時mm分ss秒" }; public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { return dtConverter.ReadJson(reader, objectType, existingValue, serializer); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { dtConverter.WriteJson(writer, value, serializer); } } //// <summary> /// 類:武林高手 /// MartialArtsMaster /// </summary> public class MartialArtsMaster { /// <summary> /// 編號 /// </summary> public int id { get; set; } /// <summary> /// 姓名 /// </summary> public string name { get; set; } /// <summary> /// 出道時間 /// </summary> [ JsonConverter(typeof(MyCnDateTimeConverter))] public DateTime DebutTime { get; set; } /// <summary> /// 生日 /// </summary> [JsonConverter(typeof(MyDateTimeConverter))] public DateTime Birthday { get; set; } }
序列化:
//日期轉換 //增加幾個武林高手 List<MartialArtsMaster> masterList = new List<MartialArtsMaster>() { new MartialArtsMaster(){ id=1, name="段譽", Birthday=new DateTime(1982,2,12,10,53,10)}, new MartialArtsMaster(){ id=2, name="喬峰", Birthday=new DateTime(1982,2,12)}, new MartialArtsMaster(){ id=3, name="虛竹", Birthday=new DateTime(1982,2,12), DebutTime=new DateTime(1982,2,12)} }; //序列化DataSet為Json字串 string myJsonStr = JsonConvert.SerializeObject(masterList,Formatting.Indented); Console.WriteLine(myJsonStr);
執行結果如下:
F.自定義成員名
我們在序列化時,不想使用屬性或欄位的名字,可以完成改名。
改名在屬性上加如下標記,即可:
[JsonProperty(PropertyName = "名字")]
G.動態成員清單
對於不同的序列化,我們需要的屬性或欄位如果不同,還可以通過清單來動態完成。
下面列舉動態構造物件成員,序列化Json
/// <summary> /// 動態動態成員 /// </summary> public class MyPropsContractResolver : DefaultContractResolver { string[] props = null; public MyPropsContractResolver(string[] props) { //屬性的清單 this.props = props; } //重寫建立要序列化的屬性 protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) { IList<JsonProperty> list = base.CreateProperties(type, memberSerialization); //只保留清單有列出的屬性 return list.Where(p => props.Contains(p.PropertyName)).ToList(); } }
通過繼承DefaultContractResolver類,重寫CreateProperties屬性清單方法
下面是呼叫,實體類還是上面的“武林高手”,這裡不再列舉。
//增加幾個武林高手 List<MartialArtsMaster> masterList = new List<MartialArtsMaster>() { new MartialArtsMaster(){ id=1, name="段譽", Birthday=new DateTime(1982,2,12,10,53,10)}, new MartialArtsMaster(){ id=2, name="喬峰", Birthday=new DateTime(1982,2,12)}, new MartialArtsMaster(){ id=3, name="虛竹", Birthday=new DateTime(1982,2,12), DebutTime=new DateTime(1982,2,12)} }; JsonSerializerSettings jsetting = new JsonSerializerSettings(); var propertiesList = new string[] { "name", "Birthday", "DebutTime" }; jsetting.ContractResolver = new MyPropsContractResolver(propertiesList); Console.WriteLine(JsonConvert.SerializeObject(masterList, Formatting.Indented, jsetting));
執行結果如下:
真正的做到了,想讓他列舉那些列就列舉那些,最主要的一點,可以不用在實體中標記了,這個非常方便。
Newtonsoft.Json的功能遠不止這些
比如 Newtonsoft.Json.Linq 提供了使用Linq查詢JSON的很多方法,希望小夥伴閒暇慢慢控究。
更加詳細的使用,可以參考官方網站的示例有100多個,還有詳細的API文件
URL:http://www.newtonsoft.com/json/help/html/SerializationSettings.htm
2. JSON通用類
對於不想使用第三方類庫的小夥伴,我整理一個JSON序列化的類庫,即於微軟自帶的序列化類。
名稱空間:KaJiMao.Common
類名:JsonHelper
檔名:JsonHelper.cs
1 using System; 2 using System.Data; 3 using System.Text; 4 using System.Collections.Generic; 5 using System.Reflection; 6 using System.Data.Common; 7 using System.Collections; 8 using System.IO; 9 using System.Text.RegularExpressions; 10 using System.Runtime.Serialization.Json; 11 12 13 namespace KaJiMao.Common 14 { 15 /// <summary> 16 /// Json通用類 17 /// Yubinfeng 18 /// Date:2015/07/11 19 20 public static class JsonHepler 21 { 22 #region List序列化為 Json 字串 23 /// <summary> 24 /// List序列化為 Json 字串 25 /// </summary> 26 /// <typeparam name="T"></typeparam> 27 /// <param name="jsonName"></param> 28 /// <param name="list"></param> 29 /// <returns></returns> 30 public static string ListToJson<T>(IList<T> list, string jsonName) 31 { 32 StringBuilder Json = new StringBuilder(); 33 if (string.IsNullOrEmpty(jsonName)) 34 jsonName = list[0].GetType().Name; 35 Json.Append("{\"" + jsonName + "\":["); 36 if (list.Count > 0) 37 { 38 for (int i = 0; i < list.Count; i++) 39 { 40 T obj = Activator.CreateInstance<T>(); 41 PropertyInfo[] pi = obj.GetType().GetProperties(); 42 Json.Append("{"); 43 for (int j = 0; j < pi.Length; j++) 44 { 45 Type type; 46 object o = pi[j].GetValue(list[i], null); 47 string v = string.Empty; 48 if (o != null) 49 { 50 type = o.GetType(); 51 v = o.ToString(); 52 } 53 else 54 { 55 type = typeof(string); 56 } 57 58 Json.Append("\"" + pi[j].Name.ToString() + "\":" + StringFormat(v, type)); 59 60 if (j < pi.Length - 1) 61 { 62 Json.Append(","); 63 } 64 } 65 Json.Append("}"); 66 if (i < list.Count - 1) 67 { 68 Json.Append(","); 69 } 70 } 71 } 72 Json.Append("]}"); 73 return Json.ToString(); 74 } 75 #endregion 76 77 #region 序列化集合物件 78 /// <summary> 79 /// 序列化集合物件 80 /// </summary> 81 public static string JsonSerializerByArrayData<T>(T[] tArray) 82 { 83 DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T[])); 84 MemoryStream ms = new MemoryStream(); 85 ser.WriteObject(ms, tArray); 86 string jsonString = Encoding.UTF8.GetString(ms.ToArray()); 87 ms.Close(); 88 string p = @"\\/Date\((\d+)\+\d+\)\\/"; 89 MatchEvaluator matchEvaluator = new MatchEvaluator(ConvertJsonDateToDateString); 90 Regex reg = new Regex(p); 91 jsonString = reg.Replace(jsonString, matchEvaluator); 92 return jsonString; 93 } 94 #endregion 95 96 #region 序列化單個物件 97 /// <summary> 98 /// 序列化單個物件 99 /// </summary> 100 public static string JsonSerializerBySingleData<T>(T t) 101 { 102 DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T)); 103 MemoryStream ms = new MemoryStream(); 104 ser.WriteObject(ms, t); 105 string jsonString = Encoding.UTF8.GetString(ms.ToArray()); 106 ms.Close(); 107 string p = @"\\/Date\((\d+)\+\d+\)\\/"; 108 MatchEvaluator matchEvaluator = new MatchEvaluator(ConvertJsonDateToDateString); 109 Regex reg = new Regex(p); 110 jsonString = reg.Replace(jsonString, matchEvaluator); 111 return jsonString; 112 } 113 #endregion 114 115 #region 反序列化單個物件 116 /// <summary> 117 /// 反序列化單個物件 118 /// </summary> 119 public static T JsonDeserializeBySingleData<T>(string jsonString) 120 { 121 //將"yyyy-MM-dd HH:mm:ss"格式的字串轉為"\/Date(1294499956278+0800)\/"格式 122 string p = @"\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}"; 123 MatchEvaluator matchEvaluator = new MatchEvaluator(ConvertDateStringToJsonDate); 124 Regex reg = new Regex(p); 125 jsonString = reg.Replace(jsonString, matchEvaluator); 126 DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T)); 127 MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)); 128 T obj = (T)ser.ReadObject(ms); 129 return obj; 130 } 131 #endregion 132 133 #region 反序列化集合物件 134 /// <summary> 135 /// 反序列化集合物件 136 /// </summary> 137 public static T[] JsonDeserializeByArrayData<T>(string jsonString) 138 { 139 //將"yyyy-MM-dd HH:mm:ss"格式的字串轉為"\/Date(1294499956278+0800)\/"格式 140 string p = @"\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}"; 141 MatchEvaluator matchEvaluator = new MatchEvaluator(ConvertDateStringToJsonDate); 142 Regex reg = new Regex(p); 143 jsonString = reg.Replace(jsonString, matchEvaluator); 144 DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T[])); 145 MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)); 146 T[] arrayObj = (T[])ser.ReadObject(ms); 147 return arrayObj; 148 } 149 #endregion 150 151 #region 將Json序列化時間轉為字串 ("yyyy-MM-dd HH:mm:ss") 152 /// <summary> 153 /// 將Json序列化的時間由/Date(1294499956278+0800)轉為字串 154 /// </summary> 155 private static string ConvertJsonDateToDateString(Match m) 156 { 157 string result = string.Empty; 158 DateTime dt = new DateTime(1970, 1, 1); 159 dt = dt.AddMilliseconds(long.Parse(m.Groups[1].Value)); 160 dt = dt.ToLocalTime(); 161 result = dt.ToString("yyyy-MM-dd HH:mm:ss"); 162 return result; 163 } 164 #endregion 165 166 #region 將時間字串轉為Json時間 167 /// <summary> 168 /// 將時間字串轉為Json時間 169 /// </summary> 170 private static string ConvertDateStringToJsonDate(Match m) 171 { 172 string result = string.Empty; 173 DateTime dt = DateTime.Parse(m.Groups[0].Value); 174 dt = dt.ToUniversalTime(); 175 TimeSpan ts = dt - DateTime.Parse("1970-01-01"); 176 result = string.Format("\\/Date({0}+0800)\\/", ts.TotalMilliseconds); 177 return result; 178 } 179 #endregion 180 181 #region ist轉成json 182 /// <summary> 183 /// List轉成json 184 /// </summary> 185 /// <typeparam name="T"></typeparam> 186 /// <param name="list"></param> 187 /// <returns></returns> 188 public static string ListToJson<T>(IList<T> list) 189 { 190 object obj = list[0]; 191 return ListToJson<T>(list, obj.GetType().Name); 192 } 193 #endregion 194 195 #region 物件轉換為Json字串 196 /// <summary> 197 /// 物件轉換為Json字串 198 /// </summary> 199 /// <param name="jsonObject">物件</param> 200 /// <returns>Json字串</returns> 201 public static string ToJson(object jsonObject) 202 { 203 try 204 { 205 StringBuilder jsonString = new StringBuilder(); 206 jsonString.Append("{"); 207 PropertyInfo[] propertyInfo = jsonObject.GetType().GetProperties(); 208 for (int i = 0; i < propertyInfo.Length; i++) 209 { 210 object objectValue = propertyInfo[i].GetGetMethod().Invoke(jsonObject, null); 211 if (objectValue == null) 212 { 213 continue; 214 } 215 StringBuilder value = new StringBuilder(); 216 if (objectValue is DateTime || objectValue is Guid || objectValue is TimeSpan) 217 { 218 value.Append("\"" + objectValue.ToString() + "\""); 219 } 220 else if (objectValue is string) 221 { 222 value.Append("\"" + objectValue.ToString() + "\""); 223 } 224 else if (objectValue is IEnumerable) 225 { 226 value.Append(ToJson((IEnumerable)objectValue)); 227 } 228 else 229 { 230 value.Append("\"" + objectValue.ToString() + "\""); 231 } 232 jsonString.Append("\"" + propertyInfo[i].Name + "\":" + value + ","); ; 233 } 234 return jsonString.ToString().TrimEnd(',') + "}"; 235 } 236 catch (Exception ex) 237 { 238 throw ex; 239 } 240 } 241 #endregion 242 243 #region 物件集合轉換Json 244 /// <summary> 245 /// 物件集合轉換Json 246 /// </summary> 247 /// <param name="array">集合物件</param> 248 /// <returns>Json字串</returns> 249 public static string ToJson(IEnumerable array) 250 { 251 string jsonString = "["; 252 foreach (object item in array) 253 { 254 jsonString += ToJson(item) + ","; 255 } 256 if (jsonString.Length > 1) 257 { 258 jsonString.Remove(jsonString.Length - 1, jsonString.Length); 259 } 260 else 261 { 262 jsonString = "[]"; 263 } 264 return jsonString + "]"; 265 } 266 #endregion 267 268 #region 普通集合轉換Json 269 /// <summary> 270 /// 普通集合轉換Json 271 /// </summary> 272 /// <param name="array">集合物件</param> 273 /// <returns>Json字串</returns> 274 public static string ToArrayString(IEnumerable array) 275 { 276 string jsonString = "["; 277 foreach (object item in array) 278 { 279 jsonString = ToJson(item.ToString()) + ","; 280 } 281 jsonString.Remove(jsonString.Length - 1, jsonString.Length); 282 return jsonString + "]"; 283 } 284 #endregion 285 286 #region Datatable轉換為Json 287 /// <summary> 288 /// Datatable轉換為Json 289 /// </summary> 290 /// <param name="table">Datatable物件</param> 291 /// <returns>Json字串</returns> 292 public static string ToJson(DataTable dt) 293 { 294 StringBuilder jsonString = new StringBuilder(); 295 jsonString.Append("["); 296 DataRowCollection drc = dt.Rows; 297 for (int i = 0; i < drc.Count; i++) 298 { 299 jsonString.Append("{"); 300 for (int j = 0; j < dt.Columns.Count; j++) 301 { 302 string strKey = dt.Columns[j].ColumnName; 303 string strValue = drc[i][j].ToString(); 304 Type type = dt.Columns[j].DataType; 305 jsonString.Append("\"" + strKey + "\":"); 306 strValue = StringFormat(strValue, type); 307 if (j < dt.Columns.Count - 1) 308 { 309 jsonString.Append(strValue + ","); 310 } 311 else 312 { 313 jsonString.Append(strValue); 314 } 315 } 316 jsonString.Append("},"); 317 } 318 jsonString.Remove(jsonString.Length - 1, 1); 319 jsonString.Append("]"); 320 if (jsonString.Length == 1) 321 { 322 return "[]"; 323 } 324 return jsonString.ToString(); 325 } 326 #endregion 327 328 #region DataTable轉成Json 329 /// <summary> 330 /// DataTable轉成Json 331 /// </summary> 332 /// <param name="jsonName"></param> 333 /// <param name="dt"></param> 334 /// <returns></returns> 335 public static string ToJson(DataTable dt, string jsonName) 336 { 337 StringBuilder Json = new StringBuilder(); 338 if (string.IsNullOrEmpty(jsonName)) 339 jsonName = dt.TableName; 340 Json.Append("{\"" + jsonName + "\":["); 341 if (dt.Rows.Count > 0) 342 { 343 for (int i = 0; i < dt.Rows.Count; i++) 344 { 345 Json.Append("{"); 346 for (int j = 0; j < dt.Columns.Count; j++) 347 { 348 Type type = dt.Rows[i][j].GetType(); 349 Json.Append("\"" + dt.Columns[j].ColumnName.ToString() + "\":" + StringFormat(dt.Rows[i][j] is DBNull ? string.Empty : dt.Rows[i][j].ToString(), type)); 350 if (j < dt.Columns.Count - 1) 351 { 352 Json.Append(","); 353 } 354 } 355 Json.Append("}"); 356 if (i < dt.Rows.Count - 1) 357 { 358 Json.Append(","); 359 } 360 } 361 } 362 Json.Append("]}"); 363 return Json.ToString(); 364 } 365 #endregion 366 367 #region DataReader轉換為Json 368 /// <summary> 369 /// DataReader轉換為Json 370 /// </summary> 371 /// <param name="dataReader">DataReader物件</param> 372 /// <returns>Json字串</returns> 373 public static string ToJson(IDataReader dataReader) 374 { 375 try 376 { 377 StringBuilder jsonString = new StringBuilder(); 378 jsonString.Append("["); 379 380 while (dataReader.Read()) 381 { 382 jsonString.Append("{"); 383 for (int i = 0; i < dataReader.FieldCount; i++) 384 { 385 Type type = dataReader.GetFieldType(i); 386 string strKey = dataReader.GetName(i); 387 string strValue = dataReader[i].ToString(); 388 jsonString.Append("\"" + strKey + "\":"); 389 strValue = StringFormat(strValue, type); 390 if (i < dataReader.FieldCount - 1) 391 { 392 jsonString.Append(strValue + ","); 393 } 394 else 395 { 396 jsonString.Append(strValue); 397 } 398 } 399 jsonString.Append("},"); 400 } 401 if (!dataReader.IsClosed) 402 { 403 dataReader.Close(); 404 } 405 jsonString.Remove(jsonString.Length - 1, 1); 406 jsonString.Append("]"); 407 if (jsonString.Length == 1) 408 { 409 return "[]"; 410 } 411 return jsonString.ToString(); 412 } 413 catch (Exception ex) 414 { 415 throw ex; 416 } 417 } 418 #endregion 419 420 #region DataSet轉換為Json 421 /// <summary> 422 /// DataSet轉換為Json 423 /// </summary> 424 /// <param name="dataSet">DataSet物件</param> 425 /// <returns>Json字串</returns> 426 public static string ToJson(DataSet dataSet) 427 { 428 string jsonString = "{"; 429 foreach (DataTable table in dataSet.Tables) 430 { 431 jsonString += "\"" + table.TableName + "\":" + ToJson(table) + ","; 432 } 433 jsonString = jsonString.TrimEnd(','); 434 return jsonString + "}"; 435 } 436 #endregion 437 438 #region 過濾特殊字元 439 /// <summary> 440 /// 過濾特殊字元 441 /// </summary> 442 /// <param name="s"></param> 443 /// <returns></returns> 444 public static string String2Json(String s) 445 { 446 StringBuilder sb = new StringBuilder(); 447 for (int i = 0; i < s.Length; i++) 448 { 449 char c = s.ToCharArray()[i]; 450 switch (c) 451 { 452 case '\"': 453 sb.Append("\\\""); break; 454 case '\\': 455 sb.Append("\\\\"); break; 456 case '/': 457 sb.Append("\\/"); break; 458 case '\b': 459 sb.Append("\\b"); break; 460 case '\f': 461 sb.Append("\\f"); break; 462 case '\n': 463 sb.Append("\\n"); break; 464 case '\r': 465 sb.Append("\\r"); break; 466 case '\t': 467 sb.Append("\\t"); break; 468 case '\v': 469 sb.Append("\\v"); break; 470 case '\0': 471 sb.Append("\\0"); break; 472 default: 473 sb.Append(c); break; 474 } 475 } 476 return sb.ToString(); 477 } 478 #endregion 479 480 #region 格式化字元型、日期型、布林型 481 /// <summary> 482 /// 格式化字元型、日期型、布林型 483 /// </summary> 484 /// <param name="str"></param> 485 /// <param name="type"></param> 486 /// <returns></returns> 487 private static string StringFormat(string str, Type type) 488 { 489 if (type != typeof(string) && string.IsNullOrEmpty(str)) 490 { 491 str = "\"" + str + "\""; 492 } 493 else if (type == typeof(string)) 494 { 495 str = String2Json(str); 496 str = "\"" + str + "\""; 497 } 498 else if (type == typeof(DateTime)) 499 { 500 str = "\"" + str + "\""; 501 } 502 else if (type == typeof(bool)) 503 { 504 str = str.ToLower(); 505 } 506 else if (type == typeof(byte[])) 507 { 508 str = "\"" + str + "\""; 509 } 510 else if (type == typeof(Guid)) 511 { 512 str = "\"" + str + "\""; 513 } 514 return str; 515 } 516 517 #endregion 518 } 519 }
==============================================================================================
<如果對你有幫助,記得點一下推薦哦,如有有不明白或錯誤之處,請多交流>
<對本系列文章閱讀有困難的朋友,請先看《.net 物件導向程式設計基礎》>
<轉載宣告:技術需要共享精神,歡迎轉載本部落格中的文章,但請註明版權及URL>
==============================================================================================