『練手』手寫一個獨立Json演算法 JsonHelper

来源:http://www.cnblogs.com/shuxiaolong/archive/2017/11/24/JsonHelper.html
-Advertisement-
Play Games

背景: > 一直使用 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
              
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 不同版本的Linux系統的啟動過程在某些地方是不一樣的,現在先來介紹一下red hat 7 的啟動過程(EFI)。 (加電→圖形登錄界面) ...
  • 0x00 前言 在Github上發現的,覺得表單很棒,不過還是少了一些,以後會陸續添加優秀乾貨,個人更新的Github以及Blog。 English Version 0x01 正文 一份精美的黑客必備表單,靈感來自於超棒的機器學習,如果您想為此列表做出貢獻(歡迎),請在github給我一個pull或 ...
  • 1、環境介紹: 都在root用戶許可權下設置時間同步 標準時鐘同步 3台設備 192.168.128 主節點 ntpd伺服器,用於與外部公共ntpd同步標準時間 192.168.129 備用主節點 ntpd客戶端,用於與ntpd同步時間 192.168.130 子節點 ntpd客戶端,用於與ntpd同 ...
  • 1.下載 sudo apt-get install skypeforlinux 2.卸載 sudo apt remove skypeforlinux ...
  • 第一章 常見的狀態碼 200 – 伺服器成功返回網頁 404 – 請求的網頁不存在 503 – 伺服器超時 1.1 臨時響應 1xx(臨時響應) 表示臨時響應並需要請求者繼續執行操作的狀態碼。 100(繼續)請求者應當繼續提出請求。伺服器返回此代碼表示已收到請求的第一部分,正在等待其餘部分。 101 ...
  • 安裝Zabbix 下載安裝zabbix的YUM源 安裝Zabbix 安裝之後進入MySQL資料庫,創建Zabbix資料庫(密碼有複雜要求) 導入Zabbix到資料庫 配置zabbix用戶 配置Zabbix伺服器端 拷貝zabbix文件到html目錄 Zabbix加入開機啟動並啟動 在瀏覽器中測試Za ...
  • 前言 最近幾個月一直在研究開源的APM和監控方案,並對比使用了Zipkin,CAT,Sky walking,PinPoint(僅對比,未實際部署),Elastic APM,TICK Stack,Prometheus等開源產品,其中不乏功能強大的監控和追蹤系統,但它們都對.NET/.NET Core沒 ...
  • 傳送門:https://www.cnblogs.com/akwwl/p/3573666.html 之前錯誤:使用layui與web uploader上傳文件都報異常,後來終於找到原因是asp.net預設最大上傳文件大小為4M,運行超時時間為90S。 解決方法 1 : 修改web.config文件可以 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...