.Net Core下一次針對dpz2.Json和Newtonsoft.Json解析庫的簡單測試

關於dpz2.Json

dpz2.Json是大胖子軟件的自研Json解析庫。

應用於更加簡單的使用場景

在dpz2.Json誕生之前,我們一直使用的是Newtonsoft.Json解析庫,Newtonsoft.Json最方便的地方是採用了類似JavaBean的綁定方式進行操作,但是實際操作時,我們可能更多時候只想要個解析器,好讓我們能快速的辨別數據,這個時候,單純的JavaBean方式又變得比較肘制,讀取數據使用C#的動態類型確實可以比較方便的進行操作。

專注於直接操作

另外一個促使我們自研一個解析庫的重要原因,就是Json語句的生成,如果生成數據類,確實可以達到快速生成的目的,但是爲每一個Json都生成數據類,將會大大的更加程序的開發成本。

舉一個簡單典型的Json數據示例:

{
  aaa:{
        bbb:[111,222],
        cc:"abc"
    },
    ddd:"qaz"
}

如果使用Newtonsoft.Json在不生成數據類的情況下,依靠C#的動態類型來完成:

dynamic obj = new Newtonsoft.Json.Linq.JObject();
dynamic aaa = obj.aaa = new Newtonsoft.Json.Linq.JObject();
Newtonsoft.Json.Linq.JArray bbb = aaa.bbb = new Newtonsoft.Json.Linq.JArray();
bbb.Add(111);
bbb.Add(222);
aaa.cc = "abc";
obj.ddd = "qaz";
Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(obj));

可以看到,如果不清楚Newtonsoft.Json下的各種類型,將會非常頭疼。

如果使用dpz2.Json,可以有效的避免這個問題:

using (var json = new dpz2.Json.JsonObject()) {
        var aaa = json.Object("aaa");
        var bbb = aaa.Array("bbb");
        bbb.Number(0).Value = 111;
        bbb.Number(1).Value = 222;
        aaa.String("cc").Value = "abc";
        json.String("ddd").Value = "qaz";
        Console.WriteLine(json.ToJsonString());
}

如果不想使用中間變量,也可以使用直接多層操作方式(這種方式的層次非常分明,但是運行效率略慢):

using (var json = new dpz2.Json.JsonObject()) {
        json.Object("aaa").Array("bbb").Number(0).Value = 111;
        json.Object("aaa").Array("bbb").Number(1).Value = 222;
        json.Object("aaa").String("cc").Value = "abc";
        json.String("ddd").Value = "qaz";
        Console.WriteLine(json.ToJsonString());
}

爲了方便操作數據,我們提供了函數模式和索引模式兩種含義不同的操作方式:函數模式爲添加/訪問自適應模式,即如訪問的對象不存在,將自動添加對象;而索引模式則爲訪問模式,如訪問的對象不存在,將會返回Null空對象。
兩種操作方式可以更具需要自由排列組合,如上例代碼可以修改爲:

using (var json = new dpz2.Json.JsonObject()) {
        json.Object("aaa").Array("bbb").Number(0).Value = 111;
        json["aaa"]["bbb"].Number(1).Value = 222;
        json["aaa"].String("cc").Value = "abc";
        json.String("ddd").Value = "qaz";
        Console.WriteLine(json.ToJsonString());
}

我們提供了兩種方式獲取數據(兩種方式是等價的,效率相仿,可按實際需求使用):

double b1 = json.Object("aaa").Array("bbb").Number(0).Value;
double b1 = json["aaa"]["bbb"][0].GetNumber();

簡單環境下 dpz2.Json VS Newtonsoft.Json 的解析效率對比

此次測試使用的是本人的開發筆記本,小新潮7000,配置爲i5-8250U/8G內存

此次測試以解析一個比較長(字符長度約爲1800+)的實際API交互數據,以一次解析加序列化爲操作,來對比兩個類庫的解析效率。

以下是測試代碼(使用Release配置編譯):

using System;

namespace demo {
    class Program {
        static void Main(string[] args) {

            string str = "{\"Header\":{\"Ver\":\"\",\"Type\":\"\",\"SessionID\":\"\",\"Time\":\"1565942801\",\"Status\":\"\",\"Error\":\"\"},\"Data\":{\"Apis\":[{\"Url\":\"/Api/Help/Get\",\"LoginNeed\":false,\"Controller\":\"Kernel.Api.HelpController\",\"Description\":\"API\u8f85\u52a9\u63a5\u53e3\uff0c\u8fd4\u56de\u670d\u52a1\u5668\u4e0a\u6240\u6709\u7684API\u5217\u8868\"},{\"Url\":\"/Api/Info/Update\",\"LoginNeed\":false,\"Controller\":\"Kernel.Api.InfoController\",\"Description\":\"\u83b7\u53d6\u66f4\u65b0\u65e5\u5fd7\"},{\"Url\":\"/Api/Info/Environment\",\"LoginNeed\":false,\"Controller\":\"Kernel.Api.InfoController\",\"Description\":\"\u83b7\u53d6\u8fd0\u884c\u73af\u5883\u4fe1\u606f\"},{\"Url\":\"/Api/Info/Debug\",\"LoginNeed\":false,\"Controller\":\"Kernel.Api.InfoController\",\"Description\":\"\u83b7\u53d6\u8fd0\u884c\u73af\u5883\u4fe1\u606f\"},{\"Url\":\"/Api/Info/Get\",\"LoginNeed\":false,\"Controller\":\"Kernel.Api.InfoController\",\"Description\":\"\u83b7\u53d6\u6240\u6709\u4e0e\u672c\u7a0b\u5e8f\u76f8\u5173\u7684 \u4fe1\u606f\"},{\"Url\":\"/Api/User/GetInfo\",\"LoginNeed\":false,\"Controller\":\"Kernel.Api.UserController\",\"Description\":\"\u4ee5Get\u65b9\u5f0f\u83b7 \u53d6\u767b\u9646\u7528\u6237\u4fe1\u606f\"},{\"Url\":\"/Api/User/PostInfo\",\"LoginNeed\":false,\"Controller\":\"Kernel.Api.UserController\",\"Description\":\" \u4ee5Post\u65b9\u5f0f\u83b7\u53d6\u767b\u9646\u7528\u6237\u4fe1\u606f\"},{\"Url\":\"/Api/User/Get\",\"LoginNeed\":false,\"Controller\":\"Kernel.Api.UserController\",\"Description\":\"\u9ed8\u8ba4\u4ea4\u4e92\uff0c\u8fd4\u56de\u7a7a\u5185\u5bb9\"},{\"Url\":\"/Api/Ycc/GetConfig\",\"LoginNeed\":false,\"Controller\":\"Kernel.Api.YccController\",\"Description\":\"\u83b7\u53d6\u914d\u7f6e\u4fe1\u606f\"},{\"Url\":\"/Api/Ycc/CreateNew\",\"LoginNeed\":false,\"Controller\":\"Kernel.Api.YccController\",\"Description\":\"\u521b\u5efa\u4e00\u4e2a\u4ea4\u4e92\u6807\u8bc6\"},{\"Url\":\"/Api/Ycc/Get\",\"LoginNeed\":false,\"Controller\":\"Kernel.Api.YccController\",\"Description\":\"\u9ed8\u8ba4\u4ea4\u4e92\uff0c\u8fd4\u56de\u7a7a\u5185\u5bb9\"}]}}";

            int tick0 = Environment.TickCount;

            dpz2.Json.Parser.EnforceUnicode = false;
            using (var json = dpz2.Json.Parser.ParseJson(str)) {
                Console.WriteLine(json.ToJsonString());
            }
            int tick1 = Environment.TickCount;

            dynamic dy = Newtonsoft.Json.JsonConvert.DeserializeObject(str);
            Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(dy));
            int tick2 = Environment.TickCount;

            Console.WriteLine($"[dpz2.Json] {tick1 - tick0}ms");
            Console.WriteLine($"[Newtonsoft.Json] {tick2 - tick1}ms");
        }
    }
}

第一次運行:

[dpz2.Json] 31ms
[Newtonsoft.Json] 438ms

第二次運行:

[dpz2.Json] 47ms
[Newtonsoft.Json] 422ms

第三次運行:

[dpz2.Json] 32ms
[Newtonsoft.Json] 422ms

第四次運行:

[dpz2.Json] 31ms
[Newtonsoft.Json] 438ms

第五次運行:

[dpz2.Json] 46ms
[Newtonsoft.Json] 469ms

dpz2.Json的解析效率還是讓人滿意的,但是Newtonsoft.Json的耗時貌似有點大,大家幫忙看看,Newtonsoft.Json是否有優化參數可以調整的,可以讓此次測試更有參考價值。

dpz2.Jso爲一個開源庫,大家可以在下列倉庫下載源代碼:

Github:https://github.com/dpzsoft/dotnet-core-dpz2-json
碼雲(Gitee):https://gitee.com/dpzsoft/dotnet-core-dpz2-json

Nuget包也同步推出:

訪問地址:https://www.nuget.org/packages/dotnet-core-dpz2-json/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章