背景: > 一直使用 Newtonsoft.Json.dll 也算挺穩定的。 > 但這個框架也挺鬧心的: > 1、影響編譯失敗:https://www.cnblogs.com/zihuxinyu/archive/2013/05/06/3063181.html (我也經常遇到) > 2、WinCE版本 ...
背景:
> 一直使用 Newtonsoft.Json.dll 也算挺穩定的。
> 但這個框架也挺鬧心的:
> 1、影響編譯失敗:https://www.cnblogs.com/zihuxinyu/archive/2013/05/06/3063181.html (我也經常遇到)
> 2、WinCE版本(小眾用戶)太大:Newtonsoft.Json.Compact.dll 352kb
> 3、自己寫一個微型框架,在通訊方面 要用到Json:一個 100k 的框架,引用一個 400k 的 Newtonsoft.Json.dll —— 總感覺 尾大不掉。
>4、不知道 目標類型,我只想將 Json反序列化成 List 和 Hash 的結構 —— 傳說中的 萬能結構,Newtonsoft.Json.dll 支持得不友好。
於是一咬牙,花 9個小時,手寫了一個 Json演算法:
> 基本支持 Newtonsoft.Json.dll 的 一切正反Json序列化:對象(字典)、集合、元數據。
> 可以將任意 Json 轉換成 List 和 Hash 的 組合結構。
> 性能只有 Newtonsoft.Json.dll 的 1/3 (超長Json反序列化, JsonHelper:10000次/秒,Newtonsoft.Json.dll 性能是 30000次/秒)。
> 性能我已經滿意了,源碼 和 性能截圖 如下。
性能測試截圖:
超長Json反序列化:
JsonHelper 性能為 10W次 12.7秒,Newtonsoft.Json.dll 性能為 10W次 3.7秒。
手寫一個嵌套實體 10W次 反序列化性能:
JsonHelper 性能為 10W次 7.8秒,Newtonsoft.Json.dll 性能為 10W次 1.3秒。
手寫一個嵌套實體 10W次 序列化:
JsonHelper 性能為 10W次 2.6秒,Newtonsoft.Json.dll 性能為 10W次 1.2秒。
JsonHelper 源碼:
1 using System; 2 using System.Collections; 3 using System.Collections.Generic; 4 using System.Collections.Specialized; 5 using System.Globalization; 6 using System.IO; 7 using System.Linq; 8 using System.Reflection; 9 using System.Text; 10 using System.Text.RegularExpressions; 11 using Newtonsoft.Json.Linq; 12 13 namespace InkFx.Utils 14 { 15 /// <summary> 16 /// 不依賴 任何第三方JSON框架的 Json 輔助類 17 /// </summary> 18 public static class JsonHelper 19 { 20 #region 公 共 函 數 21 22 /// <summary> 23 /// 將指定對象轉換成 JSON 24 /// </summary> 25 public static string JsonSerialize(object data) 26 { 27 return JsonSerialize(data, false); 28 } 29 /// <summary> 30 /// 將指定對象轉換成 JSON 31 /// </summary> 32 public static string JsonSerialize(object data, bool throwEeception) 33 { 34 if (data == null) return "null"; 35 36 try 37 { 38 JsonObject obj = ObjectToJsonObject(data); 39 return obj == null ? "null" : obj.ToJson(); 40 } 41 catch (Exception exp) 42 { 43 if (throwEeception) throw; 44 else 45 { 46 string logMsg = "JsonHelper.JsonSerialize(object data) 序列化錯誤:" + exp; 47 Tools.LogError(logMsg, "Logs/Tools/ErrorLog/"); 48 return null; 49 } 50 } 51 } 52 53 54 55 /// <summary> 56 /// 將JSON 轉換成 指定類型對象 57 /// </summary> 58 public static T JsonDeserialize<T>(string json) 59 { 60 return JsonDeserialize<T>(json, false); 61 } 62 /// <summary> 63 /// 將JSON 轉換成 指定類型對象 64 /// </summary> 65 public static T JsonDeserialize<T>(string json, bool throwEeception) 66 { 67 if (IsNullOrWhiteSpace(json)) return default(T); 68 69 try 70 { 71 JsonObject obj = StringToJsonObject(json); 72 T result = JsonObjectToObject<T>(obj); 73 return (T)result; 74 } 75 catch (Exception exp) 76 { 77 if (throwEeception) throw; 78 else 79 { 80 string logMsg = "JsonHelper.JsonDeserialize<T>(string json) 反序列化錯誤:" + exp; 81 Tools.LogError(logMsg, "Logs/Tools/ErrorLog/"); 82 return default(T); 83 } 84 } 85 } 86 /// <summary> 87 /// 將JSON 轉換成 指定類型對象 88 /// </summary> 89 public static object JsonDeserialize(string json, Type type) 90 { 91 return JsonDeserialize(json, type, false); 92 } 93 /// <summary> 94 /// 將JSON 轉換成 指定類型對象 95 /// </summary> 96 public static object JsonDeserialize(string json, Type type, bool throwEeception) 97 { 98 if (IsNullOrWhiteSpace(json)) return null; 99 100 try 101 { 102 JsonObject obj = StringToJsonObject(json); 103 object result = JsonObjectToObject(obj, type); 104 return result; 105 } 106 catch (Exception exp) 107 { 108 if (throwEeception) throw; 109 else 110 { 111 string logMsg = "JsonHelper.JsonDeserialize(string json, Type type) 反序列化錯誤:" + exp; 112 Tools.LogError(logMsg, "Logs/Tools/ErrorLog/"); 113 return null; 114 } 115 } 116 } 117 118 119 /// <summary> 120 /// 在 未指定 Json 反序列化類型 的情況下, 用 JsonObject 表達一個 Json對象 121 /// </summary> 122 public static JsonObject JsonDeserializeObject(string json) 123 { 124 return JsonDeserializeObject(json, false); 125 } 126 /// <summary> 127 /// 在 未指定 Json 反序列化類型 的情況下, 用 JsonObject 表達一個 Json對象 128 /// </summary> 129 public static JsonObject JsonDeserializeObject(string json, bool throwEeception) 130 { 131 if (IsNullOrWhiteSpace(json)) return null; 132 133 try 134 { 135 JsonObject result = StringToJsonObject(json); 136 return result; 137 } 138 catch (Exception exp) 139 { 140 if (throwEeception) throw; 141 else 142 { 143 string logMsg = "JsonHelper.JsonDeserializeObject(string json) 反序列化錯誤:" + exp; 144 Tools.LogError(logMsg, "Logs/Tools/ErrorLog/"); 145 return null; 146 } 147 } 148 } 149 /// <summary> 150 /// 在 未指定 Json 反序列化類型 的情況下, 用 字典、集合 表達一個 Json對象 151 /// </summary> 152 public static object JsonDeserializeHasnList(string json) 153 { 154 return JsonDeserializeHasnList<Hashtable>(json, false); 155 } 156 /// <summary> 157 /// 在 未指定 Json 反序列化類型 的情況下, 用 字典、集合 表達一個 Json對象 158 /// </summary> 159 public static object JsonDeserializeHasnList(string json, bool throwEeception) 160 { 161 return JsonDeserializeHasnList<Hashtable>(json, throwEeception); 162 } 163 /// <summary> 164 /// 在 未指定 Json 反序列化類型 的情況下, 用 字典、集合 表達一個 Json對象 165 /// </summary> 166 public static object JsonDeserializeHasnList<HashT>(string json) where HashT : IDictionary, new() 167 { 168 return JsonDeserializeHasnList<HashT>(json, false); 169 } 170 /// <summary> 171 /// 在 未指定 Json 反序列化類型 的情況下, 用 字典、集合 表達一個 Json對象 172 /// </summary> 173 public static object JsonDeserializeHasnList<HashT>(string json, bool throwEeception) where HashT : IDictionary, new() 174 { 175 if (IsNullOrWhiteSpace(json)) return null; 176 177 try 178 { 179 JsonObject obj = StringToJsonObject(json); 180 object result = obj.ToHashList<HashT>(); 181 return result; 182 } 183 catch (Exception exp) 184 { 185 if (throwEeception) throw; 186 else 187 { 188 string logMsg = "JsonHelper.JsonDeserializeHasnList(string json) 反序列化錯誤:" + exp; 189 Tools.LogError(logMsg, "Logs/Tools/ErrorLog/"); 190 return null; 191 } 192 } 193 } 194 195 196 /// <summary> 197 /// 將 JsonObject 實體 分析成 指定的類型 198 /// </summary> 199 public static T JsonObjectToObject<T>(JsonObject obj) 200 { 201 if (obj == null) return default(T); 202 object result = JsonObjectToObject(obj, typeof (T)); 203 return (T)result; 204 } 205 /// <summary> 206 /// 將 JsonObject 實體 分析成 指定的類型 207 /// </summary> 208 public static object JsonObjectToObject(JsonObject obj, Type type) 209 { 210 if (obj == null) return null; 211 return obj.ToObject(type); 212 } 213 214 215 #endregion 216 217 218 #region 私 有 函 數 219 220 private static DateTime m_StampRoot = new DateTime(1970, 01, 01, 00, 00, 00, 00, DateTimeKind.Utc); 221 private static readonly Regex m_RegNum = new Regex(@"\d+", RegexOptions.Compiled | RegexOptions.IgnoreCase); 222 223 /// <summary> 224 /// Json時間戳 轉 時間 225 /// </summary> 226 public static DateTime StampToDateTime(string timeStamp) 227 { 228 Match match = m_RegNum.Match(timeStamp); 229 if (!match.Success) return m_StampRoot; 230 long num = long.Parse(match.Value); 231 return StampToDateTime(num); 232 } 233 /// <summary> 234 /// Json時間戳 轉 時間 235 /// </summary> 236 public static DateTime StampToDateTime(long timeStamp) 237 { 238 return m_StampRoot.AddMilliseconds(timeStamp).ToLocalTime(); 239 } 240 /// <summary> 241 /// 時間 轉 Json時間戳 242 /// </summary> 243 public static long DateTimeToStamp(DateTime time) 244 { 245 return (long)(time.ToUniversalTime() - m_StampRoot).TotalMilliseconds; 246 } 247 248 private static bool IsNullOrWhiteSpace(string value) 249 { 250 if (value == null) return true; 251 for (int i = 0; i < value.Length; i++) 252 if (!char.IsWhiteSpace(value[i])) 253 return false; 254 return true; 255 } 256 257 #endregion 258 259 260 #region 核 心 算 法 261 262 263 private static JsonObject ObjectToJsonObject(object data) 264 { 265 if (data == null) return null; 266 267 Type type = data.GetType(); 268 269 if (ReflectHelper.IsMetaType(type)) 270 { 271 return new JsonValue(data, false); 272 } 273 else if (data is IDictionary) 274 { 275 JsonHash jsonHash = new JsonHash(); 276 IDictionary hash = (IDictionary) data; 277 foreach (object key in hash.Keys) 278 { 279 object value = hash[key]; 280 JsonObject jsonV = ObjectToJsonObject(value); 281 jsonHash[key.ToString()] = jsonV; 282 } 283 return jsonHash; 284 } 285 else if (data is IList) 286 { 287 JsonList jsonList = new JsonList(); 288 foreach (object item in (IList)data) 289 { 290 JsonObject jsonObj = ObjectToJsonObject(item); 291 if (jsonObj != null) jsonList.Add(jsonObj); 292 } 293 return jsonList; 294 } 295 else 296 { 297 Hashtable hash = new Hashtable(); 298 FieldInfo[] listField = type.GetFields(); 299 PropertyInfo[] listProp = type.GetProperties(); 300 foreach (FieldInfo field in listField) 301 { 302 object fieldObj = ReflectHelper.GetValue(data, field); 303 hash[field.Name] = fieldObj; 304 } 305 foreach (PropertyInfo prop in listProp) 306 { 307 object propObj = ReflectHelper.GetValue(data, prop); 308 hash[prop.Name] = propObj; 309 } 310 return ObjectToJsonObject(hash); 311 } 312 } 313 private static JsonObject StringToJsonObject(string json) 314 { 315 List<JsonObject> queue = new List<JsonObject>(); 316 using (JsonReader reader = new JsonReader(json)) 317 { 318 while (!reader.IsEnd) 319 { 320 string item = reader.Read(); 321 if (string.IsNullOrEmpty(item)) continue; 322 if (item.Length == 1) 323 { 324 char @char = item[0]; 325 if (@char == ARRAY_BEGIN) 326 { 327 queue.Add(new JsonList()); 328 } 329 else if (@char == OBJECT_BEGIN) 330 { 331 queue.Add(new JsonHash()); 332 } 333 else if (@char == ITEM_SPLIT) 334 { 335 MergeLastJsonKeyValue(queue); 336 } 337 else if (@char == KV_SPLIT) 338 { 339 MergeLastJsonKeyValue(queue); 340 queue.Add(new JsonKeyValue()); 341 } 342 else if (@char == ARRAY_END) 343 { 344 MergeLastJsonKeyValue(queue); 345 346 #region 搜索最近的一個數組開始 347 348 int index = queue.FindLastIndex(x => x.IsList); 349 JsonList array = (JsonList)queue[index]; 350 for (int i = index + 1, count = queue.Count; i < count; i++) array.Add(queue[i]); 351 queue.RemoveRange(index + 1, queue.Count - index - 1); 352 353 #endregion 354 } 355 else if (@char == OBJECT_END) 356 { 357 MergeLastJsonKeyValue(queue); 358 359 #region 搜索最近的一個對象開始 360 361 int index = queue.FindLastIndex(x => x.IsHash); 362 JsonHash hash = (JsonHash)queue[index]; 363 List<JsonObject> list = new List<JsonObject>(); 364 for (int i = index + 1, count = queue.Count; i < count; i++) list.Add(queue[i]); 365 List<JsonObject> listKV = list.FindAll(x => (x is JsonKeyValue)); 366 367 for (int i = 0, count = listKV.Count; i < count; i++) 368 { 369 JsonKeyValue keyValue = (JsonKeyValue)listKV[i]; 370 hash.Hash[keyValue.Key.Value.ToString()] = keyValue.Value; 371 } 372 queue.RemoveRange(index + 1, queue.Count - index - 1); 373 374 #endregion 375 } 376 } 377 else 378 { 379 queue.Add(new JsonValue(item, true)); 380 } 381 } 382 reader.Dispose(); 383 } 384 385 int queueCount = queue.Count; 386 if (queueCount == 1) return queue[0]; 387 if (queueCount >= 2) 388 { 389 JsonList jsonList = new JsonList(); 390 foreach (JsonObject item in queue) jsonList.Add(item); 391 return jsonList; 392 } 393 394 return null; 395 } 396 private static void MergeLastJsonKeyValue(List<JsonObject> queue) 397 { 398 if (queue == null || queue.Count <= 2) return; 399 int count = queue.Count; 400 401 if (queue[count - 2] is JsonKeyValue) 402 { 403 //標準情況 404 JsonObject key = queue[count - 3]; 405 if (!(key is JsonValue)) return; 406 JsonObject value = queue[count - 1]; 407 JsonKeyValue keyValue = (JsonKeyValue)queue[count - 2]; 408 keyValue.Key = (JsonValue)key; 409 keyValue.Value = value; 410 queue.RemoveAt(count - 1); 411 queue.RemoveAt(count - 3); 412 } 413 else if (queue[count - 1