[译]试用新的System.Text.Json API
译注
可能有的小伙伴已经知道了,在.NET Core 3.0中微软加入了对JSON的内置支持。
一直以来.NET开发者们已经习惯使用Json.NET这个强大的库来处理JSON。
那么.NET为什么要增加JSON的内置支持呢?
最近,.NET的官方博客再次发表文章说明了这么做的原因、并介绍了相关API的用法。
现翻译出来分享给大家。
原文地址: https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-apis/
尝试新的System.Text.Json API
对于.NET Core 3.0,我们 提供了一个名为System.Text.Json的全新命名空间 ,支持读取器/写入器,文档对象模型(DOM)和序列化。在这篇博文中,我告诉你为什么我们建造它,它是如何工作的,以及你如何试用它。
我们还有一个视频:
https://sec.ch9.ms/ch9/f427/704ea54a-dac0-4ef8-b1bc-e9fde129f427/onNET_high.mp4
获取新的JSON库
- 如果您的目标是.NET Core。安装最新版本的.NET Core 3.0预览版。这为您提供了新的JSON库和ASP.NET Core集成。
- 如果您的目标是.NET Standard或.NET Framework。安装System.Text.JsonNuGet包(确保包含预览并安装版本4.6.0-preview6.19303.8或更高版本)。为了与ASP.NET Core集成,您必须以.NET Core 3.0为目标。
.NET Core 3.0中JSON的未来
JSON已经成为几乎所有现代.NET应用程序的重要组成部分,并且在许多情况下甚至超过了XML的使用范围。但是,.NET还没有(强大的)内置方式来处理JSON。相反,我们一直依赖Json.NET,它继续为.NET生态系统提供良好的服务。
我们已经决定构建一个新的JSON库:
提供高性能的JSON API。我们需要一组新的JSON API,这些API通过使用
Span<T>可以高度优化性能, 并且可以直接处理UTF-8而无需转码为UTF-16string实例。这两个方面对于ASP.NET Core至关重要,因为吞吐量是关键要求。我们考虑过对Json.NET做出贡献,但如果不破坏现有的Json.NET客户或者破坏我们可以实现的性能,这被认为是不可能的。有了这些System.Text.Json,我们可以获得1.3倍速--5倍的速度,具体取决于场景(更多细节见下文)。我们相信我们仍然可以挤出更多。从ASP.NET Core中删除Json.NET依赖项。今天,ASP.NET Core依赖于Json.NET。虽然这提供了ASP.NET Core和Json.NET之间的紧密集成,但它也意味着Json.NET的版本由底层平台决定。但是,Json.NET经常更新,应用程序开发人员通常希望 - 甚至必须 - 使用特定版本。因此,我们希望从ASP.NET Core 3.0中删除Json.NET依赖项,以便客户可以选择使用哪个版本,而不必担心它们可能会意外破坏底层平台。
为Json.NET提供ASP.NET Core集成包。Json.NET基本上已成为.NET中JSON处理的瑞士军刀。它提供了许多选项和工具,使客户可以轻松地处理其JSON需求。我们不想在客户今天获得的Json.NET支持上妥协。例如,能够通过
AddJsonOptions扩展方法在ASP.NET Core中配置JSON序列化 。因此,我们希望为ASP.NET Core提供Json.NET集成作为开发人员可以选择安装的NuGet包,这样他们就可以获得今天从Json.NET获得的所有功能。此工作项的另一部分是确保我们拥有正确的扩展点,以便其他方可以为其选择的JSON库提供类似的集成包。
有关动机及其与Json.NET的关系的更多详细信息,请查看 我们在10月份发布的公告。
直接使用System.Text.Json
对于所有示例,请确保导入以下两个名称空间:
using System.Text.Json;
using System.Text.Json.Serialization;
使用序列化器
该 System.Text.Json 序列化器可以异步读写JSON并且对UTF-8文本进行了优化,使其成为理想的REST API和后端应用程序。
class WeatherForecast
{
public DateTimeOffset Date { get; set; }
public int TemperatureC { get; set; }
public string Summary { get; set; }
}
string Serialize(WeatherForecast value)
{
return JsonSerializer.ToString<WeatherForecast>(value);
}
默认情况下,我们生成缩小的JSON。如果要生成易读的内容,可以将 JsonSerializerOptions 的实例传递给序列化程序。这也是您配置其他设置的方式,例如处理注释,尾随逗号和命名策略。
string SerializePrettyPrint(WeatherForecast value)
{
var options = new JsonSerializerOptions
{
WriteIndented = true
};
return JsonSerializer.ToString<WeatherForecast>(value, options);
}
反序列化的工作方式类似:
// {
// "Date": "2013-01-20T00:00:00Z",
// "TemperatureC": 42,
// "Summary": "Typical summer in Seattle. Not.",
// }
WeatherForecast Deserialize(string json)
{
var options = new JsonSerializerOptions
{
AllowTrailingCommas = true
};
return JsonSerializer.Parse<WeatherForecast>(json, options);
}
我们还支持异步序列化和反序列化:
async Task SerializeAsync(WeatherForecast value, Stream stream)
{
await JsonSerializer.WriteAsync<WeatherForecast>(value, stream);
}
您还可以使用自定义属性来控制序列化行为,例如,忽略属性并在JSON中指定属性的名称:
class WeatherForecast
{
public DateTimeOffset Date { get; set; }
// 总是使用摄氏度
[JsonPropertyName("temp")]
public int TemperatureC { get; set; }
public string Summary { get; set; }
// 不序列化这个属性
[JsonIgnore]
public bool IsHot => TemperatureC >= 30;
}
我们目前不支持F#特定行为(例如有区别的联合和记录类型),但我们 计划将来添加它。
使用DOM
有时您不希望反序列化JSON有效负载,但您仍希望对其内容进行结构化访问。例如,假设我们有一组温度,并希望计算出星期一的平均温度:
[
{
"date": "2013-01-07T00:00:00Z",
"temp": 23,
},
{
"date": "2013-01-08T00:00:00Z",
"temp": 28,
},
{
"date": "2013-01-14T00:00:00Z",
"temp": 8,
},
]
使用 JsonDocument 类可以很容易地访问各个属性和值。
double ComputeAverageTemperatures(string json)
{
var options = new JsonReaderOptions
{
AllowTrailingCommas = true
};
using (JsonDocument document = JsonDocument.Parse(json, options))
{
int sumOfAllTemperatures = 0;
int count = 0;
foreach (JsonElement element in document.RootElement.EnumerateArray())
{
DateTimeOffset date = element.GetProperty("date").GetDateTimeOffset();
if (date.DayOfWeek == DayOfWeek.Monday)
{
int temp = element.GetProperty("temp").GetInt32();
sumOfAllTemperatures += temp;
count++;
}
}
var averageTemp = (double)sumOfAllTemperatures / count;
return averageTemp;
}
}
使用写入器(Writer)
写入器很容易使用:
var options = new JsonWriterOptions
{
Indented = true
};
using (var stream = new MemoryStream())
{
using (var writer = new Utf8JsonWriter(stream, options))
{
writer.WriteStartObject();
writer.WriteString("date", DateTimeOffset.UtcNow);
writer.WriteNumber("temp", 42);
writer.WriteEndObject();
}
string json = Encoding.UTF8.GetString(stream.ToArray());
Console.WriteLine(json);
}
读取器需要在不同的token类型间切换处理:
byte[] data = Encoding.UTF8.GetBytes(json);
Utf8JsonReader reader = new Utf8JsonReader(data, isFinalBlock: true, state: default);
while (reader.Read())
{
Console.Write(reader.TokenType);
switch (reader.TokenType)
{
case JsonTokenType.PropertyName:
case JsonTokenType.String:
{
string text = reader.GetString();
Console.Write(" ");
Console.Write(text);
break;
}
case JsonTokenType.Number:
{
int value = reader.GetInt32();
Console.Write(" ");
Console.Write(value);
break;
}
// Other token types elided for brevity
}
Console.WriteLine();
}
与ASP.NET Core集成
在接受或返回对象有效负载时,通过自动序列化提供ASP.NET内核中大多数JSON的使用,这反过来意味着大多数应用程序的代码与ASP.NET Core正在使用的JSON库无关。这使得从一个切换到另一个变得容易。
您可以在本文后面看到有关如何在MVC和SignalR中启用新JSON库的详细信息。
与ASP.NET Core MVC集成
在预览版5中,ASP.NET Core MVC增加了对使用JSON读写的支持 System.Text.Json。从Preview 6开始,默认情况下使用新的JSON库来序列化和反序列化JSON有效负载。
可以使用MvcOptions配置序列化程序的选项 :
services.AddControllers()
.AddJsonOptions(options => options.JsonSerializerOptions.WriteIndented = true);
如果您想切换回之前的默认使用方式Newtonsoft.Json,请执行以下操作:
安装 Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet包。
在
ConfigureServices()中加入AddNewtonsoftJson()的调用public void ConfigureServices(IServiceCollection services)
{
...
services.AddControllers()
+ .AddNewtonsoftJson()
...
}
已知的问题
System.Text.Json对OpenAPI / Swagger的支持正在进行,并且不太可能作为3.0版本的一部分提供。
与SignalR集成
System.Text.Json 现在是SignalR客户端和服务器在ASP.NET Core 3.0 Preview 5中使用的默认集线协议(Hub Protocol)。
如果您想切换回以前的默认使用 Newtonsoft.Json,那么您可以在客户端和服务器上执行此操作。
安装
Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJsonNuGet包。在客户端
HubConnectionBuilder中添加.AddNewtonsoftJsonProtocol():new HubConnectionBuilder()
.WithUrl("/chatHub")
.AddNewtonsoftJsonProtocol()
.Build();
在服务器
AddSignalR()调用中添加.AddNewtonsoftJsonProtocol():services.AddSignalR()
.AddNewtonsoftJsonProtocol();
性能
由于此功能受性能的强烈推动,我们希望分享新API的一些高级性能特征。
请记住,这些都是基于预览版本,最终数字很可能会有所不同。我们还在调整会影响性能的默认行为(例如,区分大小写)。请注意,这些都是微基准测试。您的里程肯定会有所不同,因此如果性能对您至关重要,请确保针对最能代表您工作负载的方案进行自己的测量。如果您遇到希望我们进一步优化的方案,请提交错误。
原生 System.Text.Json
只需进行微基准测试即可 System.Text.Json 与Json.NET 进行比较 ,得出以下结果:
| 场景 | 速度 | 内存 |
|---|---|---|
| 反序列化 | 快2倍 | 持平或更低 |
| 序列化 | 快1.5倍 | 持平或更低 |
| 文件(只读) | 快3-5倍 | <1 MB无分配 |
| 读取器 | 快2-3倍 | 无分配(直到实现值(materialize values)) |
| 写入器 | 快1.3-1.6倍 | 无分配 |
ASP.NET Core MVC 中的 System.Text.Json
我们编写了一个ASP.NET Core应用程序,可以动态生成 数据 ,然后从MVC控制器进行序列化和反序列化 。然后我们改变有效载荷大小并测量结果:
JSON反序列化(输入)
| 描述 | 吞吐量(RPS) | CPU (%) | 内存 (MB) |
|---|---|---|---|
| Newtonsoft.Json – 500 B | 136,435 | 95 | 172 |
| System.Text.Json – 500 B | 167,861 | 94 | 169 |
| Newtonsoft.Json – 2.4 KB | 97,137 | 97 | 174 |
| System.Text.Json – 2.4 KB | 32,026 | 96 | 169 |
| Newtonsoft.Json – 40 KB | 7,712 | 88 | 212 |
| System.Text.Json – 40 KB | 16,625 | 96 | 193 |
JSON序列化(输出)
| 描述 | 吞吐量(RPS) | CPU(%) | 内存(MB) |
|---|---|---|---|
| Newtonsoft.Json - 500 B | 120,273 | 94 | 174 |
| System.Text.Json - 500 B | 145,631 | 94 | 173 |
| Newtonsoft.Json - 8 KB | 35,408 | 98 | 187 |
| System.Text.Json - 8 KB | 56,424 | 97 | 184 |
| Newtonsoft.Json - 40 KB | 8,416 | 99 | 202 |
| System.Text.Json - 40 KB | 14,848 | 98 | 197 |
对于最常见的有效负载大小, System.Text.Json 在输入和输出格式化期间,MVC的吞吐量增加约20%,内存占用量更小。
摘要
在.NET Core 3.0中,我们将发布新的 System.Text.Json API,它们提供对JSON的内置支持,包括读取器/写入器,只读DOM和序列化/反序列化。主要目标是性能,我们看到的一般速度比Json.NET高出2倍,但这取决于您的场景和有效负载,因此请确保衡量对您来说重要的因素。
ASP.NET Core 3.0包含支持 System.Text.Json,默认情况下已启用。
试试 System.Text.Json 吧,然后反馈给我们!
{"happy": "coding!"}
[译]试用新的System.Text.Json API的更多相关文章
- 在.Net Core 3.0中尝试新的System.Text.Json API
.NET Core 3.0提供了一个名为System.Text.Json的全新命名空间,它支持reader/writer,文档对象模型(DOM)和序列化程序.在此博客文章中,我将介绍它如何工作以及如何 ...
- 【译】System.Text.Json 的下一步是什么
.NET 5.0 最近发布了,并带来了许多新特性和性能改进.System.Text.Json 也不例外.我们改进了性能和可靠性,并使熟悉 Newtonsoft.Json 的人更容易采用它.在这篇文章中 ...
- .NET Core 3.0 System.Text.Json 和 Newtonsoft.Json 行为不一致问题及解决办法
行为不一致 .NET Core 3.0 新出了个内置的 JSON 库, 全名叫做尼古拉斯 System.Text.Json - 性能更高占用内存更少这都不是事... 对我来说, 很多或大或小的项目能少 ...
- 使用System.Text.Json处理Json文档以及部分坑
System.Text.Json处理Json文档需要用到JsonDocument,JsonElement,JsonProperty. JsonDocument就是一个表示Json文档的东西,JsonE ...
- .NET Core 内置的 System.Text.Json 使用注意
System.Text.Json 是 .NET Core 3.0 新引入的高性能 json 解析.序列化.反序列化类库,武功高强,但毕竟初入江湖,炉火还没纯青,使用时需要注意,以下是我们在实现使用中遇 ...
- Net core 2.x 升级 3.0 使用自带 System.Text.Json 时区 踩坑经历
.Net Core 3.0 更新的东西很多,这里就不多做解释了,官方和博园大佬写得很详细 关于 Net Core 时区问题,在 2.1 版本的时候,因为用的是 Newtonsoft.Json,配置比较 ...
- [.Net Core 3.0+/.Net 5] System.Text.Json中时间格式化
简介 .Net Core 3.0开始全新推出了一个名为System.Text.Json的Json解析库,用于序列化和反序列化Json,此库的设计是为了取代Json.Net(Newtonsoft.Jso ...
- .NET 5的System.Text.Json的JsonDocument类讲解
本文内容来自我写的开源电子书<WoW C#>,现在正在编写中,可以去WOW-Csharp/学习路径总结.md at master · sogeisetsu/WOW-Csharp (gith ...
- 使用.Net6中的System.Text.Json遇到几个常见问题及解决方案
前言 以前.NetCore是不内置JSON库的,所以大家都用Newtonsoft的JSON库,而且也确实挺好用的,不过既然官方出了标准库,那更方便更值得我们多用用,至少不用每次都nuget安装Newt ...
随机推荐
- Hutool 3.0.8 发布,Java 工具集
Hutool 是一个Java工具包,提供了丰富的文件.日期.日志.正则.字符串.配置文件等工具方法,并封装了一套简单易用的ORM框架. 主页:http://hutool.cn/ 文档:http://h ...
- API Hook基本原理和实现
API Hook基本原理和实现 2009-03-14 20:09 windows系统下的编程,消息message的传递是贯穿其始终的.这个消息我们可以简单理解为一个有特定意义的整数,正如我们看过的老故 ...
- CenOS7 docker部署lnmp环境
Step1:下载lnmp镜像 [root@docker html]# docker pull winstonpro/lnmp Step2:启动lnmp镜像的docker实例 [root@docker ...
- vfp9写的爬虫前段,基于webbrowser
*基于xmlhttp不能正确获取js动态加载的数据 CLEAR ALL CLEAR PUBLIC zform zform = CREATEOBJECT([myform])zform.go(" ...
- SQL SERVER中UPDLOCK ,READPAST使用
原文:SQL SERVER中UPDLOCK ,READPAST使用 SQL SERVER中中获取不重复数据: select top 1 * from orders with(UPDLOCK ,READ ...
- UWP中String 转为Path Data
定义方法: Geometry PathMarkupToGeometry(string pathMarkup) { string xaml = "<Path " + " ...
- Android零基础入门第83节:Activity间数据传递方法汇总
在Activity间传递的数据一般比较简单,但是有时候实际开发中也会传一些比较复杂的数据,本节一起来学习更多Activity间数据的传递. 一.常用数据类型 在前面几节我们只学习了一些常用类型的数据传 ...
- 新兴技术袭来,Web开发如何抉择?
土豆网同步更新:http://www.tudou.com/plcover/VHNh6ZopQ4E/ 使用HTML 创建Mac OS App 视频教程. 官方QQ群: (1)App实践出真知 434 ...
- Cleanmymac X 4.4.3 激活破解版|兼容mac最新系统-Mac电脑清理工具
CleanMyMac X 4.4.3 激活破解版为最新版清理工具,为你所爱的东西腾出空间.CleanMyMac拥有一系列巧妙的新功能,它可以安全.智能地扫描和清理整个系统,删除大的未使用的文件,卸载不 ...
- C#最新功能(6.0、7.0)
一直用C#开发程序,.NET的功能越来越多,变化也挺大的,从最初的封闭,到现在的开源,功能不断的增加,一直在进步.作为C#的强烈支持者,C#的变化,我不能不关注,这篇文章主要介绍,C#6.0和C#7. ...