日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

对 JsonConvert 的认识太肤浅了,终于还是遇到了问题

發布時間:2023/12/4 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 对 JsonConvert 的认识太肤浅了,终于还是遇到了问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一:背景

1. 講故事

在開始本文之前,真的好想做個問卷調查,到底有多少人和我一樣,對 JsonConvert 的認識只局限在?SerializeObject?和?DeserializeObject?這兩個方法上(┬_┬), 這樣我也好結伴同行,不再孤單落魄????????????,或許是這兩個方法基本上能夠解決工作中 80% 的場景,對于我來說確實是這樣,但隨著編碼的延續,終究還是會遇到那剩下的 20% ,所以呀。。。

我的場景是這樣的:前段時間寫業務代碼的時候,我有一個自定義的客戶算法類型的Model,這個Model中有這種算法類型下的客戶群以及Report統計信息,還用了 HashSet 記錄了該類型下的 CustomerID集合,為了方便講述,我把Model簡化如下:

class CustomerAlgorithmModel{public string DisplayName { get; set; }public int CustomerType { get; set; }public ReprotModel Report { get; set; }public HashSet<int> CustomerIDHash { get; set; }}class ReprotModel{public int TotalCustomerCount { get; set; }public int TotalTradeCount { get; set; }}

那有意思的就來了,我個人是有記日志的癖好,就想著以后不會出現死無對證的情況,然后就理所當然的使用?JsonConvert.SerializeObject, 這一下就出問題了,日志送入到了?ElasticSearch?,然后通過?Kibana?查不出來,為啥呢?看完上面的 Model 我想你也猜到了原因,json體太大了哈,好歹?CustomerIDHash?中也有幾十萬個撒,這一下全導出成json了,這 size 還能小嗎?要不我寫段代碼看一看。

static void Main(string[] args){var algorithModel = new CustomerAlgorithmModel(){CustomerType = 1,DisplayName = "????????",Report = new ReprotModel(){TotalCustomerCount = 1000,TotalTradeCount = 50},CustomerIDHash = new HashSet<int>(Enumerable.Range(1, 500000))};var json = JsonConvert.SerializeObject(algorithModel);File.WriteAllText("1.txt", json, Encoding.UTF8);Console.WriteLine("寫入完成!");}

可以看到,僅一個json就?3.3M,這樣的記錄多來幾打后,在?kibana?上一檢索,瀏覽器就卡的要死,其實?CustomerIDHash?這個字段對我來說是可有可無的,就算存下來了也沒啥大用,所以需求就來了,如何屏蔽掉?CustomerIDHash。

二:尋求解決方案

1. 使用 JsonIgnore

有問題就網上搜啊,這一搜馬上就有人告訴你可以使用?JsonIgnoreAttribute?忽略特性,加好這個特性后繼續跑一下程序。

[Newtonsoft.Json.JsonIgnore]public HashSet<int> CustomerIDHash { get; set; }

太好了,終于搞定了,但是靜下心來想一想,總感覺心里有那么一點不舒服,為什么這么說,一旦你給這個?CustomerIDHash?套上了?JsonIgnore?,這就意味著它在 JsonConvet 的世界中從此消失,也不管是誰在使用這個Model, 但這并不是我的初衷,我的初衷僅僅是為了在記錄日志的時候踢掉?CustomerIDHash,可千萬不要影響在其他場景下的使用哈,現在這種做法就會給自己,給別人挖坑,埋下了不可預知的bug,我想你應該明白我的意思,還得繼續尋找下一個方案。

2. 使用自定義的 JsonConverter

真的,Newtonsoft?太強大了,我都想寫一個專題好好彌補彌補我的知識盲區,其實在這個場景中不就是想把?HashSet<int>?給屏蔽掉嘛,Newtonsoft?中專門提供了一個針對特定類型的自定義處理類,接下來我就寫一段:

/// <summary>/// 自定義一個 針對 HashSet<int> 的轉換類/// </summary>public class HashSetConverter : Newtonsoft.Json.JsonConverter<HashSet<int>>{public override HashSet<int> ReadJson(JsonReader reader, Type objectType, HashSet<int> existingValue, bool hasExistingValue, JsonSerializer serializer){return existingValue;}public override void WriteJson(JsonWriter writer, HashSet<int> value, JsonSerializer serializer){writer.WriteNull();}}

就是這么簡單,然后就可以在?SerializeObject?的時候指定下自定義的?HashSetConverter?即可,然后再將程序跑起來看一下。

var json = JsonConvert.SerializeObject(algorithModel, Formatting.Indented, new HashSetConverter());

從圖中看,貌似也是解決了,但我突然發現自己要鉆牛角尖了,如果我的實體中又來了一個頂級優質客戶群的?TopNCustomerIDHash,但因為這個CustomerID 比較少,我希望在 Json 中能保留下來,然后就是踢掉的那個 CustomerIDHash 我要保留?CustomerIDHash.Length,哈哈,搞事情哈,那接下來怎么解決呢?

  • 修改 Model 實體

class CustomerAlgorithmModel{public HashSet<int> CustomerIDHash { get; set; }// topN 優質客戶群public HashSet<int> TopNCustomerIDHash { get; set; }}
  • HashSetConverter 增加邏輯鑒別是否為保留字段

public override void WriteJson(JsonWriter writer, HashSet<int> value, JsonSerializer serializer){if (writer.Path == "TopNCustomerIDHash"){writer.WriteStartArray();foreach (var item in value){writer.WriteValue(item);}writer.WriteEndArray();}else{writer.WriteValue(value.Count);}}
  • 最后給 TopNCustomerIDHash 賦值

var algorithModel = new CustomerAlgorithmModel(){CustomerType = 1,DisplayName = "????????",Report = new ReprotModel(){TotalCustomerCount = 1000,TotalTradeCount = 50},CustomerIDHash = new HashSet<int>(Enumerable.Range(1, 500000)),TopNCustomerIDHash = new HashSet<int>(Enumerable.Range(1, 10)),};

三塊都搞定后就可以把程序跑起來了,如下圖:

貌似鉆牛角尖的問題是解決了,既然鉆牛角尖肯定要各種鄙視,比如這里的 ReportModel 我是不需要的,CustomerType 我也是不需要的,我僅僅需要看一下?DisplayName?和?TotalCustomerCount?這兩個字段就可以了, 那這個要怎么解決呢?

3. 使用 匿名類型

確實很多時候記日志,就是為了跟蹤 Model 中你特別關心的那幾個字段,所以摻雜了多余的字段確實也是沒必要的,這里可以用匿名來解決,我就來寫一段代碼:

var json = JsonConvert.SerializeObject(new{algorithModel.DisplayName,algorithModel.Report.TotalCustomerCount}, Formatting.Indented);

三:總結

雖然阻擊了幾個回合,但同時也發現了?Newtonsoft?中還有特別多的未挖掘功能,真的需要好好研究研究,源碼已下好,接下來準備做個系列來解剖一下,值得一提的是?.Net中已自帶了?System.Text.Json.JsonSerializer?類,目前來看功能還不算太豐富,簡單用用還是可以的,本篇就說到這里,希望對您有幫助。

總結

以上是生活随笔為你收集整理的对 JsonConvert 的认识太肤浅了,终于还是遇到了问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。