為什么需要新的JSON API??

          JSON.NET?大家都用過,老版本的ASP.NET Core也依賴于JSON.NET。?

          然而這個(gè)依賴就會(huì)引起一些版本問題:例如ASP.NET?Core某個(gè)版本需要使用JSON.NET?v10,而另一個(gè)庫(kù)需要使用JSON.NET?v11;或者
          JSON.NET?出現(xiàn)了一個(gè)新版本,而ASP.NET Core還不能支持這個(gè)版本,而您卻想使用該版本。?

          ?

          System.Text.Json?

          隨著NET Core?3.0的出現(xiàn),出現(xiàn)了System.Text.Json命名空間和它下面一些用于處理JSON的類。?

          ?

          特點(diǎn)

          這個(gè)內(nèi)置JSON API具有與生俱來的高性能、低分配的特點(diǎn):?

          JSON.NET?使用.NET?里面的字符串作為基本數(shù)據(jù)類型,其實(shí)也就是UTF16,而.NET Core中新的JSON?API直接使用數(shù)據(jù)原始的UTF8格式。
          ?

          新的JSON API基于Span<byte>這個(gè)數(shù)據(jù)類型來進(jìn)行操作JSON數(shù)據(jù),從而具有低分配的特點(diǎn),這就可以極大的改善吞吐量和內(nèi)存使用情況。?

          ?

          但是新的JSON?API的特性還不那么豐富,有一些JSON.NET具有的特性都還不支持。?

          ?

          例子?

          隨便找了一個(gè)JSON示例文件:?

          ?

          針對(duì)這個(gè)文件,需要修改一下它的屬性:?

          ?

          Utf8JsonReader?

          先使用?Utf8JsonReader?來讀取JSON文件。?

          Utf8JsonReader?并不會(huì)讀取文件或者stream,它會(huì)讀取Span數(shù)據(jù)類型。?

          ?

          直接上代碼:?

          Main方法里面,我們使用File.ReadAllBytes從sample.json文件讀取數(shù)格式為byte[],然后通過AsSpan這個(gè)擴(kuò)展方法將其轉(zhuǎn)化為
          Span<byte>數(shù)據(jù)類型,然后把它傳遞到?Utf8JsonReader?的構(gòu)造函數(shù)來創(chuàng)建一個(gè)JSON的reader。?

          ?

          接下來使用while循環(huán)對(duì)JSON數(shù)據(jù)的每個(gè)Token進(jìn)行讀取,每次執(zhí)行Read()方法時(shí),reader就會(huì)移動(dòng)到JSON數(shù)據(jù)里面的下一個(gè)Token那里。?

          ?

          Token分成幾種類型,GetTokenInfo方法就是判斷一下Token的類型,并返回一些描述性信息,這里面應(yīng)該是包含了所有的類型。這里面使用到了C#?8?
          的?switch?表達(dá)式。?

          ?

          運(yùn)行程序?

          結(jié)果如下:?

          可以看到sample.json文件里面的每個(gè)Token都被正確的顯示了。?

          ?

          JsonDocument類?

          JsonDocument是基于Utf8JsonReader?構(gòu)建的。JsonDocument?可分析?JSON?數(shù)據(jù)并生成只讀文檔對(duì)象模型?(DOM)
          ,可對(duì)模型進(jìn)行查詢,以支持隨機(jī)訪問和枚舉。使用?JsonDocument?分析常規(guī)?JSON?有效負(fù)載并訪問其所有成員比使用?Json.NET?快?2-3?
          倍,且為合理大?。?< 1 MB)的數(shù)據(jù)所分配的量非常少。?

          JsonDocument可以處理Span,也可以處理Stream。?

          ?

          例子:?

          這里我通過File.OpenRead把json文件轉(zhuǎn)化為stream。然后使用JsonDocument.Parse方法把stream解析成JSON
          文檔對(duì)象模型。?

          注意,這里我使用了C# 8的using var語(yǔ)法,這個(gè)以后再說。?

          ?

          下面我們開始從這個(gè)JSON文檔對(duì)象模型的根節(jié)點(diǎn)開始遍歷,也就是RootElement:?

          ?

          然后通過root這個(gè)JsonElement類型的對(duì)象的GetProperty方法來獲得相應(yīng)的屬性,而且這個(gè)方法可以連串使用:?

          最后一行使用GetString方法來獲得該屬性的字符串值。?

          ?

          然后我們可以寫一個(gè)遞歸調(diào)用的方法來遍歷整個(gè)模型的每個(gè)屬性:?

          這個(gè)方法接受JsonElement類型的對(duì)象,然后對(duì)該元素的屬性進(jìn)行循環(huán)。?

          如果當(dāng)前屬性是另一個(gè)對(duì)象,那么就繼續(xù)遞歸調(diào)用這個(gè)方法;?

          否則就輸出原始的文本。?

          ?

          最后調(diào)用該方法:?

          ?

          輸出結(jié)果為:?

          與json文件的內(nèi)容匹配。?

          ?

          Utf8JsonWriter類?

          下面研究一下如何寫入json文件。這里需要使用Utf8JsonWriter類。?

          直接看代碼:?

          這個(gè)類需要傳遞的參數(shù)類型是Stream或者Buffer,也就是向Stream或Buffer里面寫入數(shù)據(jù)。?

          ?

          那么就提供一個(gè)buffer:?

          ?

          下面單獨(dú)寫一個(gè)方法,來生成json數(shù)據(jù):?

          參數(shù)類型是Utf8JsonWriter。通過智能提示可以看到它提供了很多用于寫入不同類型數(shù)據(jù)的方法。?

          ?

          寫JSON對(duì)象?

          現(xiàn)在我想寫一個(gè)json對(duì)象,那么就從WriteStartObject()開始,然后以WriteEndObject()結(jié)束:?

          這樣的話,實(shí)際上我已經(jīng)擁有了一個(gè)合法的json文檔。?

          ?

          寫屬性和值?

          可以分開寫屬性和值:?

          ?

          也可以同時(shí)把屬性和值寫出來:?

          ?

          顯示JSON數(shù)據(jù)?

          我先寫這些內(nèi)容,然后在Main方法里面調(diào)用一下:?

          ?

          首先需要告訴writer把它的內(nèi)容flush給buffer,使用這個(gè)buffer我們可以獲得writer的輸出,這樣的話就會(huì)得到一個(gè)byte數(shù)組,然后把這個(gè)
          byte數(shù)組轉(zhuǎn)化為字符串,這樣就可以在控制臺(tái)顯示它了:?

          ?

          運(yùn)行一下看看效果:?

          沒啥太大的問題,就是格式不好看。?

          ?

          對(duì)輸出進(jìn)行格式化?

          .NET Core提供了一個(gè)JsonWriterOptions類,它可以對(duì)Writer進(jìn)行一些設(shè)置。?

          這里對(duì)輸出進(jìn)行了縮進(jìn),最后把這個(gè)options傳遞給Utf8JsonWriter的構(gòu)造函數(shù)即可。?

          ?

          再次運(yùn)行:?

          現(xiàn)在好看多了。?

          ?

          JsonSerializer?

          前面幾節(jié)的內(nèi)容可能稍微有點(diǎn)底層,我們大部分時(shí)候可能只需要對(duì)C#的類進(jìn)行串行化或者將JSON數(shù)據(jù)反串行化成C#類,在.NET Core?3.0里面,我們可以使用
          JsonSerializer這個(gè)類來做這些事情。?

          ?

          例子:


          還是使用之前用到的json數(shù)據(jù):?

          ?

          然后我們需要建建立兩個(gè)類,對(duì)應(yīng)這個(gè)文件:?

          ?

          反串行化?

          可以使用JsonSerializer類的Deserialize()方法對(duì)json數(shù)據(jù)反串行化。這個(gè)方法支持三種類型的輸入?yún)?shù),分別是:?

          *
          JSON數(shù)據(jù)的字符串?

          *
          Utf8JsonReader?

          *
          ReadOnlySpan<byte>,它里面包含JSON數(shù)據(jù)?

          ?

          為了簡(jiǎn)單一點(diǎn),我直接把json文件讀取成字符串,然后傳給Deserialize方法:?

          然后我試圖打印出反串行化之后的一些屬性數(shù)據(jù)。但是這不會(huì)成功。因?yàn)镴SON文件里面數(shù)據(jù)的大小寫命名規(guī)范使用的是camel casing
          (簡(jiǎn)單理解為首字母是小寫的),而默認(rèn)情況下Deserializer會(huì)尋找Pascal casing這種規(guī)范(簡(jiǎn)單理解為每個(gè)單詞的首字母都是大寫的)的屬性名。?

          ?

          格式化?

          為解決這個(gè)問題,就需要使用JsonSerializerOptions類:?

          建立該類的一個(gè)實(shí)例,設(shè)置PropertyNamingPolicy為CamelCase,然后把這個(gè)實(shí)例傳遞給Deserialize方法的第二個(gè)參數(shù)。?

          ?

          運(yùn)行看結(jié)果:?

          這次就沒有問題了。?

          ?

          串行化?

          JsonSerializer也支持串行化,也就是把C#數(shù)據(jù)轉(zhuǎn)化為JSON數(shù)據(jù):?

          這里使用了相同的options。?

          ?

          運(yùn)行結(jié)果:?

          ?

          如果想讓輸出結(jié)果更好看一些,可以在JsonSerializerOptions里面進(jìn)行相應(yīng)的設(shè)置:?

          ?

          這次輸出結(jié)果為:?

          ?

          總結(jié)?

          總結(jié)一下.NET Core 3.0新的JSON?API:?

          *
          Utf8JsonReader -?讀操作,快速,低級(jí)?

          *
          Utf8JsonWriter -?寫操作,快速,低級(jí)?

          *
          JsonDocument?-?基于DOM,快速?

          *
          JsonSeriliazer -?串行化/反串行化,快速?

          ?

          另外?JSON.NET?仍然被支持。?

          友情鏈接
          ioDraw流程圖
          API參考文檔
          OK工具箱
          云服務(wù)器優(yōu)惠
          阿里云優(yōu)惠券
          騰訊云優(yōu)惠券
          京東云優(yōu)惠券
          站點(diǎn)信息
          問題反饋
          郵箱:[email protected]
          QQ群:637538335
          關(guān)注微信

                国产一卡二卡在线观看 | 公交车被cao到合不拢腿漫画0 | 偷拍自拍在线播放 | 揉我胸啊嗯~出水了 | 青娱乐成人在线视频 |