2025-11-14

[C#] TOON vs JSON:在 .NET 實測序列化效能的真實結果

最近在研究一個有趣的資料交換格式 —— TOON (Token-Oriented Object Notation)

主打「低 Token 消耗」與「高結構可讀性」

由於目前 TOON 也開始有 .NET 的實作版本(例如 ToonNet 與 ToonSharp)

我就想測試一下它在實際序列化(Serialize)與反序列化(Deserialize)時的表現如何



最後我採用 ToonNet ,原因我最後在說

我用的是一個模擬假資料的模型 SampleData,裡面包含常見欄位像是 Id, Name, Email, Age, Salary ..

並且每筆資料還會有一個小的好友清單 Friends,裡面會有兩筆資料

這次測試使用 Bogus 套件來生成 10,000 筆測試資料,加上好友的大概會有三萬個物件

//建立假資料格式 var fakerZh = new Faker("zh_TW"); // 中文 var faker = new Faker<SampleData>("en") .RuleFor(x => x.Id, f => Guid.NewGuid()) // Guid .RuleFor(x => x.Name, f => f.Name.FullName()) // string .RuleFor(u => u.Email, (f, u) => f.Internet.Email(u.Name)) //Email .RuleFor(x => x.IsActive, f => f.Random.Bool()) // bool .RuleFor(x => x.Age, f => f.Random.Int(18, 80)) // int .RuleFor(x => x.Salary, f => f.Random.Decimal(min: 1.00m, max: 1000.00m)) // decimal .RuleFor(x => x.Create, f => f.Date.Past(2)) //Datetime .RuleFor(x => x.Addr, f => fakerZh.Address.FullAddress()) // 中文地址 .RuleFor(x => x.CheineseName, f => fakerZh.Name.LastName() + fakerZh.Name.FirstName());// 中文名稱 中文排版問題&#65292;先是FirstName+LastName for (var i = 1; i <= 5; i++) { //Prepare Data var data = faker.Generate(10_000); foreach (var d in data) { d.Friends = faker.Generate(2); } //TEST TOON var sw = Stopwatch.StartNew(); var toonStr = ToonNet.ToonNet.Encode(data); Console.WriteLine("TOON Length:" + toonStr.Length); Console.WriteLine(sw.Elapsed); sw.Restart(); var newToonData = ToonNet.ToonNet.Decode<List<SampleData>>(toonStr); Console.WriteLine("TOON Deserialize List Count:" + newToonData.Count()); Console.WriteLine(sw.Elapsed); Console.WriteLine("--\r\n"); //TEST JSON var sw1 = Stopwatch.StartNew(); var jsonStr = Newtonsoft.Json.JsonConvert.SerializeObject(data); Console.WriteLine("JSON Length:" + jsonStr.Length); Console.WriteLine(sw1.Elapsed); sw1.Restart(); Console.WriteLine("JSON Deserialize List Count:" + Newtonsoft.Json.JsonConvert.DeserializeObject<List<SampleData>>(jsonStr).Count()); Console.WriteLine(sw1.Elapsed); Console.WriteLine("==\r\n"); }

這段程式邏輯很單純,就是:

先產生資料;

使用 ToonNet 做序列化與反序列化;

接著使用 JSON (Newtonsoft.Json) 做同樣的動作;

最後印出資料長度與執行時間。

結果:

TOON Length:7347204 00:00:01.6336676 TOON Deserialize List Count:10000 00:00:02.2930853 -- JSON Length:8407197 00:00:00.3537226 JSON Deserialize List Count:10000 00:00:00.6373288 == TOON Length:7347089 00:00:00.6213259 TOON Deserialize List Count:10000 00:00:01.5129740 -- JSON Length:8407082 00:00:00.1623491 JSON Deserialize List Count:10000 00:00:00.1392289 == TOON Length:7347134 00:00:00.5848503 TOON Deserialize List Count:10000 00:00:01.6306873 -- JSON Length:8407127 00:00:00.1292341 JSON Deserialize List Count:10000 00:00:00.1408039 == TOON Length:7347152 00:00:00.5305677 TOON Deserialize List Count:10000 00:00:01.4916888 -- JSON Length:8407145 00:00:00.1151954 JSON Deserialize List Count:10000 00:00:00.1231848 == TOON Length:7346314 00:00:00.4511246 TOON Deserialize List Count:10000 00:00:01.3426280 -- JSON Length:8406307 00:00:00.1488930 JSON Deserialize List Count:10000 00:00:00.2019341 ==

很明顯測試,序列化之後的確文字體積變小了,但是在序列化跟反序列化中速度都不如行之有年的 JSON.net 

不過可能隨著之後的進步會有所加速,說一下為何最後我不用 ToonSharp 因為不知道為什麼,在反序列化的過程中

他會一直出現 

Unhandled exception. ToonSharp .ToonException: Line 100002: Array count mismatch: expected 10000 items, got 1

目前看起來無解,網路上查一下也沒有答案,我就換套件測試,當然這不能說 TOON 一定慢於 JSON 

畢竟這跟套件的成熟度也會有很大的關係。

--

Before you read this, the article was in a superposition of human and AI. Upon observation, the wave function collapsed into a sleep-deprived developer.

如果這篇文章有幫助到您幫我分享一下,讓我有寫下去的動力...