[译]试用新的System.Text.Json API

译注

尝试新的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-16 string 实例。这两个方面对于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,请执行以下操作:

  1. 安装 Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet包。

  2. 在 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,那么您可以在客户端和服务器上执行此操作。

  1. 安装 Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson NuGet包。

  2. 在客户端 HubConnectionBuilder 中添加 .AddNewtonsoftJsonProtocol() :

    new HubConnectionBuilder()
    .WithUrl("/chatHub")
    .AddNewtonsoftJsonProtocol()
    .Build();
  3. 在服务器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 B136,43595172
System.Text.Json – 500 B167,86194169
Newtonsoft.Json – 2.4 KB97,13797174
System.Text.Json – 2.4 KB32,02696169
Newtonsoft.Json – 40 KB7,71288212
System.Text.Json – 40 KB16,62596193

JSON序列化(输出)

描述吞吐量(RPS)CPU(%)内存(MB)
Newtonsoft.Json - 500 B120,27394174
System.Text.Json - 500 B145,63194173
Newtonsoft.Json - 8 KB35,40898187
System.Text.Json - 8 KB56,42497184
Newtonsoft.Json - 40 KB8,41699202
System.Text.Json - 40 KB14,84898197

对于最常见的有效负载大小, 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!"}

原文地址:https://www.cnblogs.com/waku/p/11026630.html

.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com 
640?wx_fmt=jpeg


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/315337.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

牛客挑战赛47 C 条件(Floyd bitset优化)

牛客挑战赛47 C 条件 思路&#xff1a;首先我们要两个图&#xff0c;一个是一定能到达的&#xff0c;一个是可能到达的&#xff0c;如果我们使用floyd (n^3)就有可能会超时&#xff0c;因为只要求询问能否到达&#xff0c;所以权值只有0和1&#xff0c;那我们可以使用bitset来…

牛客练习赛75 D 减数游戏(队列优化(需要取模的)堆)

牛客练习赛75 D 减数游戏 思路:写一下式子可以发每次选择最小的两个数进行操作&#xff0c;最后得到的答案会是最大的&#xff0c;那我们可以将它放进一个最小堆中来维护&#xff0c;但是里面的数是需要取模的&#xff0c;当它取模的时候&#xff0c;将会变小。那我们可以用一…

C#规范整理·资源管理和序列化

源管理&#xff08;尤其是内存回收&#xff09;曾经是程序员的噩梦&#xff0c;不过在.NET平台上这个噩梦似乎已经不复存在。CLR在后台为垃圾回收做了很多事情&#xff0c;使得我们现在谈起在.NET上进行开发时&#xff0c;都会说还是new一个对象吧&#xff01;回收&#xff1f;…

Codeforces Round #615 (Div. 3) A-F

传送门 这场比较简单&#xff0c;简单的题就不说题意了。 A. 问加nnn个数&#xff0c;能否使a,b,ca,b,ca,b,c相等。 直接先加到相等再看看模333是否为000即可。 //#pragma GCC optimize(2) #include<cstdio> #include<iostream> #include<string> #incl…

使用Elasticsearch 构建 .NET 企业级搜索

最近几年出现的云计算为组织和用户带来了福音。组织对客户的了解达到前所未有的透彻&#xff0c;并能够采用个性化通信锁定客户。用户几乎可以随时随地获取其数据&#xff0c;使其更加易于访问和使用。为了存储所有这些数据&#xff0c;大型数据中心遍布全世界。但是&#xff0…

牛客练习赛73 D 离别(线段树+右端点排序离线查询)

牛客练习赛73 D 离别 思路: 对于每一个固定的右端点i&#xff0c;我们都找到一个区间&#xff08;l,r&#xff09;使得区间中的点为左端点时 里面最大的的种数为k。 这个可以用队列或者vector来维护。 然后我们对于q个查询&#xff0c;安装r从小到大排序。 开始遍历&#xff0…

书籍推荐:《More Effective C#》

很多年前看过Bill Wagner的《Effective C#》第一版&#xff0c;涵盖了C#2.0相关语言特性的最佳实践&#xff0c;教我们怎样更优雅地去编写C#代码&#xff0c;当时觉得受益匪浅。最近拿到了《More Effective C#》第二版&#xff0c;目前看了大概三分之二&#xff0c;让我对C#的的…

Codeforces Round #717 (Div. 2) D(倍增dp)

Codeforces Round #717 (Div. 2) D 题意:n个数 q个询问&#xff0c;每一个询问有l和r&#xff0c;问你l到r这段区间中最少能分成几段&#xff0c;每一段中的数都是互质的。 思路&#xff1a;首先预处理出每一个点向左走最多能走多远&#xff0c;可以分解质因数来找&#xff0c…

Codeforces Round #716 (Div. 2) D(随机算法)

Codeforces Round #716 (Div. 2) D 题意:区间查询&#xff0c;问区间最少能分成几部分使得最多的数不超过总数的一半 向上取整。 思路:找到区间的总数s&#xff0c;如果不超过一半的话就是一部分。超过一半的话&#xff0c;那我们只要考虑超过一半的那一个数怎么组合&#xff…

牛客挑战赛30 C 小G砍树 换根dp+组合

链接&#xff1a;https://ac.nowcoder.com/acm/contest/18072/E 题目&#xff1a;给你一棵n个节点的带标号无根树。每次&#xff0c;你可以选择一个度数为1的节点并将它从树上移除。问总共有多少种不同的方式能将这棵树删到只剩 1 个点。两种方式不同当且仅当至少有一步被删除的…

换根dp求树所有节点的最小深度

链接&#xff1a;https://ac.nowcoder.com/acm/contest/18072/A 牛妹有一张连通图&#xff0c;由n个点和n-1条边构成&#xff0c;也就是说这是一棵树&#xff0c;牛妹可以任意选择一个点为根&#xff0c;根的深度为0&#xff0c;对于任意一个非根的点&#xff0c;我们将他到根节…

译 | 介绍全新 Microsoft.Data.SqlClient

原文&#xff1a;Diego翻译&#xff1a;Edi Wang本文由 SqlClient 和 SQL 服务器工具上的项目经理 Vicky Harp 撰写。那些一直密切关注 .NET 开发的人很可能看到 Scott Hunter 的最新博客文章&#xff0c;即《.NET Core 是 .NET 的未来》。.NET Framework 将重点转向稳定性&…

Linux下Jenkins与GitHub自动构建NetCore与部署

今天我们来谈谈NetCore在Linux底下的持续集成与部署。NetCore我就不多介绍了&#xff0c;持续集成用的是Jenkins&#xff0c;源代码管理器用的是GitHub。我们就跟着博文往下走吧。1.Linux环境在进行自动构建之前&#xff0c;我们需要一个可以运行的Linux环境&#xff0c;并保证…

容器化之后如何节省云端成本?(二十七)

如何节约云端成本&#xff1f;上云在大部分情况下就是为了降低成本&#xff0c;在这方面&#xff0c;主流的容器服务基本上都能够有效地降低成本——不仅能够高效自动化的管理和控制容器&#xff0c;极大地降低了DevOps的维护成本&#xff0c;而且不需支付Kubernetes Master节点…

2020牛客多校第1场I-1 or 2一般图最大匹配带花树

链接&#xff1a;https://ac.nowcoder.com/acm/contest/5666/I Bobo has a graph with n vertices and m edges where the i-th edge is between the vertices ai​ and bi​. Find out whether is possible for him to choose some of the edges such that the i-th vertex is…

Codeforces Round #609 (Div. 2) D. Domino for Young 黑白染色

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 给你个不规则的网络格子&#xff0c;有nnn列&#xff0c;每列有aia_iai​个格子&#xff0c;让你将121212的多米诺骨牌无重叠的放进去&#xff0c;问最多能放多少个。 思路&#xff1a; 首先如果点数小的话…

Network 黑暗爆炸 - 3732 倍增lca || Kruskal重构树

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 思路&#xff1a; 两点间最长边最小值一定是最小生成树上两点间的最大值&#xff0c;这个比较容易证&#xff0c;就不多说了。 知道这个结论后&#xff0c; 我们直接跑一个KruskalKruskalKruskal建树&#x…

Manacher入门

写在前面 manachermanachermanacher比想象中好理解得多 至少它给了我学习字符串的信心 能干啥 manachermanachermanacher&#xff0c;中文马拉车&#xff08;您别说&#xff0c;这名字还挺形象&#xff09;&#xff0c;主要用于计算字符串每一个位置为对称中心的回文串长度&a…

HDU.6761.Minimum Index(Lyndon分解)

题目大意&#xff1a;给一个字符串&#xff0c;求字符串的所有前缀的最小后缀&#xff1b; 思路&#xff1a;主要还是要理解Lyndon串的算法的整一个过程 参考&#xff1a;搬运来自 #include <iostream> #include <cstdio> #include <fstream> #include <…

C#规范整理·异常与自定义异常

这里会列举在C#中处理CLR异常方面的规范&#xff0c;帮助大家构建和开发一个运行良好和可靠的应用系统。前言迄今为止&#xff0c;CLR异常机制让人关注最多的一点就是“效率”问题。其实&#xff0c;这里存在认识上的误区&#xff0c;因为正常控制流程下的代码运行并不会出现问…