主頁 > .NET開發 > .NET Core 3.0 里新的JSON API

.NET Core 3.0 里新的JSON API

2020-09-22 04:59:58 .NET開發

為什么需要新的JSON API 

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

然而這個依賴就會引起一些版本問題:例如ASP.NET Core某個版本需要使用JSON.NET v10,而另一個庫需要使用JSON.NET v11;或者JSON.NET 出現了一個新版本,而ASP.NET Core還不能支持這個版本,而您卻想使用該版本, 

 

System.Text.Json 

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

 

特點

這個內置JSON API具有與生俱來的高性能、低分配的特點: 

JSON.NET 使用.NET 里面的字串作為基本資料型別,其實也就是UTF16,而.NET Core中新的JSON API直接使用資料原始的UTF8格式, 

新的JSON API基于Span<byte>這個資料型別來進行操作JSON資料,從而具有低分配的特點,這就可以極大的改善吞吐量和記憶體使用情況, 

 

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

 

例子 

隨便找了一個JSON示例檔案: 

"post Title": "Programming" , 
"language": 
"author": 
"firstName": "Nick", 
"lastName": "Carter" 
"publishedAt 
"wordCount " : 
13435, 
"isoriginal"? 
true, 
"tags" ? 
? "C#", "JSON API", ".NET Core" ]

 

針對這個檔案,需要修改一下它的屬性: 

sample.json File P 「 operties 
Advanced 
Custom T00 一 Namespace 
Custom T00- 
Copy to Output 「 to 
Build Action 
〔 を

 

Utf8JsonReader 

先使用 Utf8JsonReader 來讀取JSON檔案, 

Utf8JsonReader 并不會讀取檔案或者stream,它會讀取Span資料型別, 

 

直接上代碼: 

static void Elgin(stringC] 
gx?gs 
File . ReadAllBytes( path: "sample.json" ); 
var dataBytes 
dataBytes .AsSpan( ) ; 
var jsonSpan 
new Utf8JsonReader(jsonSpan); 
var jsonReader = 
while (jsonReader.Read()) 
Console . jsonReader)); 
I reference 
private static string GetTokenInfo(Utf8JsonReader jsonReader) 
jsonReader . TokenType switch 
JsonTokenType.StartObject 
"START OBJECT" , 
JsonTokenType 
. EndObject "END OBJECT" , 
JsonTokenType.StartArray 
"START ARRAY" , 
JsonTokenType. EndArray "End ARRAY" , 
JsonTokenType. PropertyName $ " PROPERTY: {jsonReader.GetString()}" , 
$"COMMENT: {jsonReader.GetString()}" , 
JsonTokenType 
. Comment 
JsonTokenType.String $"STRING: {jsonReader.GetString()}" , 
$"NUMBER: {jsonReader.GetInt32()}" , 
JsonTokenType.Number 
$"BOOL: {jsonReader.GetBoolean()}" , 
JsonTokenType 
. True 
$"BOOL: {jsonReader.GetBoolean()}" , 
JsonTokenType 
JsonTokenType.Null 
"NULL" , 
$ TOKEN: {jsonReader.TokenType}"

Main方法里面,我們使用File.ReadAllBytessample.json檔案讀取數格式為byte[],然后通過AsSpan這個擴展方法將其轉化為Span<byte>資料型別,然后把它傳遞到 Utf8JsonReader 的建構式來創建一個JSON的reader 

 

接下來使用while回圈對JSON資料的每個Token進行讀取,每次執行Read()方法時,reader就會移動到JSON資料里面的下一個Token那里, 

 

Token分成幾種型別,GetTokenInfo方法就是判斷一下Token的型別,并回傳一些描述性資訊,這里面應該是包含了所有的型別,這里面使用到了C# 8  switch 運算式, 

 

運行程式 

結果如下: 

hema Selected> 
"post Title": "Programming" , 
"language": 
"author": 
"lastName": "Carter" 
"firstName": 
"publishedAt 
"Nick", 
"wordCount " : 
13435, 
"isoriginal"? 
true, 
"tags" ? 
? "C#", "JSON 
API", ".NET Core" 
PROPERTY: postTit1e 
STRING: Programming 
PROPERTY: language 
STRING: 
PROPERTY: author 
START OBJECT 
PROPERTY: firstName 
STRING: Nick 
PROPERTY: lastName 
STRING: carter 
END OBJECT 
PROPERTY: publishedAt 
STRING: 
PROPERTY: wordcount 
NUMBER: 13435 
PROPERTY: isoriginal 
BOOL: True 
PROPERTY: tags 
START ARRAY 
STRING: 
STRING: JSON API 
STRING: .NET core 
End ARRAY 
END OBJECT

可以看到sample.json檔案里面的每個Token都被正確的顯示了, 

 

JsonDocument 

JsonDocument是基于Utf8JsonReader 構建的JsonDocument 可分析 JSON 資料并生成只讀檔案物件模型 (DOM),可對模型進行查詢,以支持隨機訪問和列舉,使用 JsonDocument 分析常規 JSON 有效負載并訪問其所有成員比使用 Json.NET  2-3 倍,且為合理大小(即 < 1 MB)的資料所分配的量非常少, 

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

 

例子: 

using 
using 
var 
var 
File .0penRead( path: 
"sample.json"); 
stream = 
JsonDocument . Parse( stream) ; 
doc

這里我通過File.OpenReadjson檔案轉化為stream,然后使用JsonDocument.Parse方法把stream決議成JSON檔案物件模型, 

注意,這里我使用了C# 8using var語法,這個以后再說, 

 

下面我們開始從這個JSON檔案物件模型的根節點開始遍歷,也就是RootElement 

root 
var 
doc . Root Element;

 

然后通過root這個JsonElement型別的物件的GetProperty方法來獲得相應的屬性,而且這個方法可以連串使用: 

firstName 
var 
root .GetProperty( "author") 
. GetProperty( "firstName" ) 
. GetString( ) ;

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

 

然后我們可以寫一個遞回呼叫的方法來遍歷整個模型的每個屬性: 

EnumerateElement(JsonElement root) 
private static void 
foreach (var prop in root. EnumerateObject()) 
if (prop.Value.ValueKind = 
JsonValueKind .0bject) 
Console . WriteLine($" {prop . Name}" ) ; 
Console.WriteLine(" 
- Object Start - 
EnumerateElement(prop . Value); 
Console.WriteLine(" 
Object End 
else 
{prop. Value.GetRawText()}");

這個方法接受JsonElement型別的物件,然后對該元素的屬性進行回圈, 

如果當前屬性是另一個物件,那么就繼續遞回呼叫這個方法; 

否則就輸出原始的文本, 

 

最后呼叫該方法: 

File. OpenRead( 
"sample.json"); 
using var stream 
path: 
JsonDocument . Parse( stream) ; 
using var doc - 
doc . Root Element; 
var root 
var firstName 
root .GetProperty( "author") 
. GetProperty( "firstName" ) 
. GetString( ) 
Console.WriteLine($"First Name is {firstName}"); 
EnumerateElement(root);

 

輸出結果為: 

First Name 
post Title: 
language: 
author 
is Nick 
" Programmi ng" 
Object Start 
irstName: "Nick" 
lastName: "Carter" 
Object End 
publishedAt : 
22T2?: 21 . ee?z" 
rdcount: 13435 
isoriginal: true 
ags: [ "C#", " 
JSON API 
% ".NET core" :

與json檔案的內容匹配, 

 

Utf8JsonWriter 

下面研究一下如何寫入json檔案,這里需要使用Utf8JsonWriter類, 

直接看代碼: 

這個類需要傳遞的引數型別是Stream或者Buffer,也就是向StreamBuffer里面寫入資料, 

 

那么就提供一個buffer 

var buffer = 
new 
= new Utf8JsonWriter(buffer); 
using var 
'son

 

下面單獨寫一個方法,來生成json資料: 

PopulateJson(Utf8JsonWriter json) 
private static void 
Json. 
write 
W rite 
W r ite Base64St ringVaIue 
W r ite Boolean 
W r ite BooleanVaIue 
W r iteCo m mentVaIue 
Write EndArray 
W r ite EndObject 
Wr iteNuII 
W r ite NullVaIue 
Write Number 
W rite Nu mbe rVaIue 
void 
void 
void 
void 
void 
void 
void 
void 
void 
void 
void 
(JsonEncodedText propertyName, ReadOnIyS 
Writes the pre-encoded property name and 
a name/value pair of a JSON object. 
utf8PropertyName, Re; 
propertyName, ReadO 
(string propertyName,

引數型別是Utf8JsonWriter,通過智能提示可以看到它提供了很多用于寫入不同型別資料的方法, 

 

JSON物件 

現在我想寫一個json物件,那么就從WriteStartObject()開始,然后以WriteEndObject()結束: 

json . WriteStartObject( ); 
json.WriteEndObject();

這樣的話,實際上我已經擁有了一個合法的json檔案, 

 

寫屬性和值 

可以分開寫屬性和值: 

json . WritePropertyName( "title"); 
json . WriteStringValue( " Programming" ) ;

 

也可以同時把屬性和值寫出來: 

json .WriteString( propertyName: "language" , 
"C#"); 
value:

 

顯示JSON資料 

我先寫這些內容,然后在Main方法里面呼叫一下: 

grgs) 
static void Mgin(stringC] 
new ArrayBufferWriter<byte>(); 
var buffer - 
new Utf8JsonWriter(buffer); 
using var Ison = 
PopulateJson( j son) ; 
I reference 
private static void PopulateJson(Utf8JsonWriter json) 
Json. 
Json. 
Json. 
Json. 
Json. 
Json. 
Json. 
WriteStartObject( ) ; 
WritePropertyName( "title"); 
WriteStringValue( " Programming" ) ; 
WriteString( propertyName: "language" , 
WriteString( propertyName: "firstName" , 
WriteString( propertyName: "lastName" , 
WriteEndObject( ) ; 
"C#"); 
value: 
"Nick"); 
value: 
"Carter"); 
value:

 

首先需要告訴writer把它的內容flush給buffer,使用這個buffer我們可以獲得writer的輸出,這樣的話就會得到一個byte陣列,然后把這個byte陣列轉化為字串,這樣就可以在控制臺顯示它了: 

new ArrayBufferWriter<byte>(); 
var buffer = 
new Utf8JsonWriter(buffer); 
using var Ison = 
PopulateJson( json); 
json. Flush(); 
var output = buffer.WrittenSpan.ToArray(); 
Encoding. UTF8. GetString(output); 
var outJson - 
Console. WriteLine(outJson);

 

運行一下看看效果: 

{"title" : "Programming" , "language" : "C#" , "firstName" : "Nick" , "lastName" : "Carter"}

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

 

對輸出進行格式化 

.NET Core提供了一個JsonWriterOptions類,它可以對Writer進行一些設定, 

var options = 
Indented = 
new JsonWriterOptions 
true 
new Utf8JsonWriter(buffer, 
using var Ison = 
options);

這里對輸出進行了縮進,最后把這個options傳遞給Utf8JsonWriter的建構式即可, 

 

再次運行: 

"title": "Programming", 
"language" ? " 
"firstName": "Nick", 
"lastName" : "Carter"

現在好看多了, 

 

JsonSerializer 

前面幾節的內容可能稍微有點底層,我們大部分時候可能只需要對C#的類進行串行化或者將JSON資料反串行化成C#類,在.NET Core 3.0里面,我們可以使用JsonSerializer這個類來做這些事情, 

 

例子:

還是使用之前用到的json資料: 

"post Title": "Programming" 
"language": 
"author": 
"firstName": "Nick", 
"lastName": "Carter" 
"publishedAt 
"wordCount " : 
13435, 
"isoriginal"? 
true, 
"tags" ? 
"JSON API", ".NET Core"

 

然后我們需要建建立兩個類,對應這個檔案: 

public class 
BlogPost 
O references 
public 
O references 
public 
O references 
public 
O references 
public 
O references 
public 
O references 
public 
public 
I reference 
{ get; set; } 
string 
Post Title 
{ get; set; } 
string 
Language 
{ get; set; } 
Author Author 
{ get; set; 
DateTime PublishedAt 
{ get; set; } 
int 
WordCount 
{ get; set; } 
bool 
Isoriginal 
:iag$ 
{ get; set; } 
stringC] 
public class Author 
O references 
{ get; set; } 
public string 
FirstName 
O references 
{ get; set; } 
public string 
LastName

 

反串行化 

可以使用JsonSerializer類的Deserialize()方法對json資料反串行化,這個方法支持三種型別的輸入引數,分別是: 

  • JSON資料的字串 

  • Utf8JsonReader 

  • ReadOnlySpan<byte>,它里面包含JSON資料 

 

為了簡單一點,我直接把json檔案讀取成字串,然后傳給Deserialize方法: 

var text = 
var post = 
File. ReadAllText( path: 
"sample. json"); 
JsonSerializer . text); 
Console . WriteLine(post. PostTitle); 
Console . WriteLine($" {post .Author . FirstName} 
{post .Author . LastName}"); 
Console . WriteLine( post. PublishedAt);

然后我試圖列印出反串行化之后的一些屬性資料,但是這不會成功,因為JSON檔案里面資料的大小寫命名規范使用的是camel casing(簡單理解為首字母是小寫的),而默認情況下Deserializer會尋找Pascal casing這種規范(簡單理解為每個單詞的首字母都是大寫的)的屬性名, 

 

格式化 

為解決這個問題,就需要使用JsonSerializerOptions類: 

var 
var 
options = 
new JsonSeria1izerOptions 
PropertyNamingPolicy = 
JsonNamingPolicy . CamelCase 
post = 
JsonSerializer.Deserialize<BlogPost>(text, options);

建立該類的一個實體,設定PropertyNamingPolicyCamelCase,然后把這個實體傳遞給Deserialize方法的第二個引數, 

 

運行看結果: 

Programmi ng 
Nick - Carter 
18/22/2819 PM

這次就沒有問題了, 

 

串行化 

JsonSerializer也支持串行化,也就是把C#資料轉化為JSON資料: 

這里使用了相同的options 

 

運行結果: 

 

如果想讓輸出結果更好看一些,可以在JsonSerializerOptions里面進行相應的設定: 

 

這次輸出結果為: 

 

總結 

總結一下.NET Core 3.0新的JSON API 

  • Utf8JsonReader - 讀操作,快速,低級 

  • Utf8JsonWriter - 寫操作,快速,低級 

  • JsonDocument - 基于DOM,快速 

  • JsonSeriliazer - 串行化/反串行化,快速 

 

另外 JSON.NET 仍然被支持, 

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/101966.html

標籤:.NET Core

上一篇:.NetCore——中小企業架構及通用權限管理系統開篇

下一篇:(22)ASP.NET Core2.2 EF創建模型(索引、備用鍵、繼承、支持欄位)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more