『練手』手寫一個獨立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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...