.NET Core3发布Json API

我们给DNC3(.NET Core 3)上了一个新包,叫做System.Text.Json(点我下载),支持读写器,DOM(文档对象模型),和序列化,在这篇博文里,我会告诉大家为什么要做这个,这个包怎样工作,你们可以怎么去用它。

也可以看视频:

https://sec.ch9.ms/ch9/f427/704ea54a-dsec.ch9.ms

获取新Json库

  • 面向DNC开发:安装DNC3的最新预览版,可获得新json库还有ASP.DNC的集成。

  • 面向.NET Standard或DNF开发:安装这个包(确定nuget允许预览版,版本需要4.6.0-preview6.19303.8或更高),没有ASP.DNC的集成。

JSON在DNC3中的前景

Json已经成为了所有现代.NET应用的重要部分,在许多情况下超过了XML的使用数量,但是.NET还没有一个很好的内建JSON处理方案,在此之前我们一直依靠Json.NET,来为.NET生态服务。

现在我们决定建立一个新的Json库:

  • 高性能的JSON API。我们需要一批新的Json api,用Span<T>达成高性能,直接处理UTF-8编码而不用转码成UTF-16的字串。两方面对ASP.DNC都很重要,因为吞吐量非常关键。我们考虑过把代码提交给Json.NET,但是既要达成我们所要的性能,又不破坏Json.NET的客户使用体验几乎是不可能的。用了System.Text.Json,视方案不同可以得到1.3-5倍的性能加速(下面有更多细节),相信还能压榨出更多性能。

  • 从ASP.DNC中移除Json.NET的依赖。 现在ASP.DNC依赖Json.NET,这样ASP.DNC和Json.NET的耦合不仅高,还使得Json.NET的版本被平台所限制。但是Json.NET经常更新,应用开发者经常想要——或者必须使用特定的版本,因此我们打算从ASP.DNC3移除Json.NET的依赖,这样客户便可以选择适用版本,不需要担心意外崩掉后台。

  • Json.NET提供了一个ASP.DNC的集成包。Json.NET基本变成了.NET处理json的瑞士军刀。这玩意提供了很多选项和工具,允许客户便利地处理json需求,我们不想让客户体验打折(原文compromise直译折中),举个蛎子,调用AddJsonOptions扩展方法即可在ASP.DNC中配置Json序列化。因此,我们准备对ASP.DNC提供一个Json.NET集成包,开发者可以选择安装,这样他们就可以在新版本中继续使用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; }// Always in Celsius.[JsonPropertyName("temp")]public int TemperatureC { get; set; }public string Summary { get; set; }// Don't serialize this property.[JsonIgnore]public bool IsHot => TemperatureC >= 30;
}

目下还不支持F#的特殊行为(例如discriminated unions(可区分联合)和record types(记录类型)),以后会加。

使用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;}
}

使用写入器

直接可以使用:

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);
}

读取器需要切换下令牌类型:

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.DNC的集成

接受或返回对象负载时,ASP.DNC中的大部分Json使用都靠自动序列化,换句话说你的绝大多数应用代码不知道ASP.DNC用的是哪个Json库,这样切换很容易。

在这可以看到在MVC和SignalR中如何启用新Json库。

和ASP.DNC MVC的集成

在pre5版本中,ASP.DNC MVC添加了System.Text.Json读写json的支持,从pre6开始,新的json库将成为序列化和反序列化json的默认选项。

用MvcOptions就可以使用序列化器:

services.AddControllers().AddJsonOptions(options => options.JsonSerializerOptions.WriteIndented = true);

如果你想换回去用Newtonsoft.json,需要:

1.从nuget上安装它;

2.在ConfigureServices() 添加 AddNewtonsoftJson() 调用:

 public void ConfigureServices(IServiceCollection services){...services.AddControllers().AddNewtonsoftJson()...}

已知问题

  • System.Text.Json对OpenAPI / Swagger的支持还在开展,不太可能作为DNC3正式版的一部分发布。

和SignalR的集成

从DNC3Pre5开始,System.Text.Json是SignalR客户端和服务器的默认核心协议了。如果你想换回Newtonsoft.Json,那么客户端和服务端都可以这么做:

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

  2. 在客户端,向HubConnectionBuilder添加AddNewtonsoftJsonProtocol()调用:

new HubConnectionBuilder().WithUrl("/chatHub").AddNewtonsoftJsonProtocol()
.Build();

3.在服务端,让AddSignalR()调用AddNewtonsoftJsonProtocol();

services.AddSignalR().AddNewtonsoftJsonProtocol();

性能

既然性能推动我们改良特性,那么我们就需要说说新API带来的高性能。

记住这些测试是基于预览版的,正式版的数据很可能大不相同,我们仍然在修改会影响性能的默认行为(比如大小写敏感),注意这些都是微测试,你实际能得到的好处可能会大不一样,因此如果你很在意性能,确保你自己的检测能代表你的负载,如果你遇到希望我们进一步优化的方案,请提交bug。

对System.Text.Json和Json.NET进行微测试,生成如下结果:

场景	         速度        内存消耗
反序列化         2倍	    持平或更低
序列化           1.5倍	    持平或更低
文档 (只读)	 3-5倍      文件<1MB时几乎无分配
读取器	         2-3倍      几乎无分配 (在你测试之前)
写入器           1.3-1.6倍  几乎无分配

对ASP.DNC MVC的System.Text.Json进行测试:

我们写了个生成数据的ASP.DNC应用,从MVC控制器序列化和反序列化,然后康康负载大小和测量结果(RPS越高越好):

对于最普遍的负载大小,MVC的System.Text.Json在输入和输出时以更小的内存占用达到了20%的吞吐量增加。

总结

DNC3正式版会带上System.Text.Json API,属于DNC内建的Json支持,包括读写器,只读DOM,序列化和反序列化。一开始的目标是性能,一般可以有超过Json.NET2倍的性能,但是这取决于你的方案和负载,因此需要确保你的重点。

ASP.DNC3添加了System.Text.Json的支持, 默认启用。

试试System.Text.Json并向我们反馈!

{"happy": "coding!"}

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

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

相关文章

Java ThreadLocal

** 一&#xff1a;ThreadLocal的简要介绍及使用 ** Java中的ThreadLocal类允许我们创建只能被同一个线程读写的变量。因此&#xff0c;如果一段代码含有一个ThreadLocal变量的引用&#xff0c;即使两个线程同时执行这段代码&#xff0c;它们也无法访问到对方的ThreadLocal变…

P5591 小猪佩奇学数学(单位根反演)

P5591 小猪佩奇学数学 ∑i0n(in)pi⌊ik⌋⌊ik⌋i−i%kk1k∑i0n(in)pi(i−i%k)1k∑i0n(in)pii−1k∑i0n(in)pi(imodk)\sum_{i 0} ^{n} (_i ^ n) \times p ^ i \times \lfloor \frac{i}{k} \rfloor\\ \lfloor \frac{i}{k} \rfloor \frac{i - i \% k}{k}\\ \frac{1}{k} \sum_{i …

认证方案之初步认识JWT

前言&#xff1a;现在越来越多的项目或多或少会用到JWT&#xff0c;为什么会出现使用JWT这样的场景的呢&#xff1f;假设现在有一个APP&#xff0c;后台是分布式系统。APP的首页模块部署在上海机房的服务器上&#xff0c;子页面模块部署在深圳机房的服务器上。此时你从首页登录…

Java实现生产消费模型的5种方式

** 前言 ** 生产者和消费者问题是线程模型中的经典问题&#xff1a;生产者和消费者在同一时间段内共用同一个存储空间&#xff0c;生产者往存储空间中添加产品&#xff0c;消费者从存储空间中取走产品&#xff0c;当存储空间为空时&#xff0c;消费者阻塞&#xff0c;当存储…

C#.NET 一颗璀璨的全能明星

C# 是微软推出的一种基于.NET框架的、面向对象的高级编程语言&#xff0c;她可以做什么呢&#xff1f;1.桌面开发&#xff0c;WinForm/GUI可视化编程&#xff1a;Windows开发中的葵花宝典&#xff0c;霸主地位至今无出其右&#xff0c;开发效率令人发指&#xff0c;大部分营销软…

#3328. PYXFIB(单位根反演)

#3328. PYXFIB ∑i0⌊nk⌋CnikFik∑i0nCniFi[i≡0(modk)]i≡0(modk)&#xff0c;单位根反演有1k∑j0k−1wkij1k∑i0nCniFi∑j0k−1wkij\sum_{i 0} ^{\lfloor \frac{n}{k} \rfloor} C_{n} ^{i \times k} \times F_{i \times k}\\ \sum_{i 0} ^{n} C_n ^{i} \times F_i \times …

Leetcode 86. 分隔链表

给定一个链表和一个特定值 x&#xff0c;对链表进行分隔&#xff0c;使得所有小于 x 的节点都在大于或等于 x 的节点之前。你应当保留两个分区中每个节点的初始相对位置。示例:输入: head 1->4->3->2->5->2, x 3输出: 1->2->2->4->3->5题目分析…

深入理解 JVM Class文件格式(一)

** 一、JVM体系结构 ** ** 二、class格式文件概述 ** class文件是一种8位字节的二进制流文件&#xff0c; 各个数据项按顺序紧密的从前向后排列&#xff0c; 相邻的项之间没有间隙&#xff0c; 这样可以使得class文件非常紧凑&#xff0c; 体积轻巧&#xff0c; 可以被J…

min_25 推导及例题总结

min_25 筛 一个亚线性筛&#xff0c;复杂度大概是O(n34log⁡n)O(\frac{n ^{\frac{3}{4}}}{ \log n})O(lognn43​​)。 使用min_25min\_25min_25求前缀和&#xff0c;有两个基本特征&#xff1a;① 积性函数&#xff0c;② 满足质数点为多项式。 算法思路 给定n≤1011n \leq…

asp.net core 使用 signalR(一)

asp.net core 使用 signalR&#xff08;一&#xff09;IntroSignalR 是什么&#xff1f;ASP.NET Core SignalR 是一个开源代码库&#xff0c;它简化了向应用添加实时 Web 功能的过程。实时 Web 功能使服务器端代码能够即时将内容推送到客户端。SignalR 的适用对象&#xff1a;需…

深入理解 JVM Class文件格式(二)

** class文件中的特殊字符串 ** 特殊字符串是常量池中符号引用的一部分&#xff0c;包括三种&#xff1a; 类的全限定名&#xff0c; 字段和方法的描述符&#xff0c; 特殊方法的方法名。 下面我们就分别介绍这三种特殊字符串。 &#xff08;1&#xff09; 类的全限定名 在…

P4211 [LNOI2014]LCA(离线 + 在线 做法)

P4211 [LNOI2014]LCA 有一棵根节点为111树&#xff0c;有mmm次询问&#xff0c;每次给定l,r,zl, r, zl,r,z&#xff0c;输出∑ilrdep[lca(i,z)]\sum\limits_{i l} ^{r} dep[lca(i, z)]il∑r​dep[lca(i,z)]。 乍一看这题好像无从下手&#xff0c;仔细想想lca(i,z)lca(i, z)l…

.NET框架之“小马过河”

.NET框架之“小马过河”有许多流行的 .NET框架&#xff0c;大家都觉得挺“重”&#xff0c;认为很麻烦&#xff0c;重量级&#xff0c;不如其它“轻量级”框架&#xff0c;从而不愿意使用。面对形形色色的框架发愁&#xff0c;笔者也曾发愁。但我发现只要敢于尝试&#xff0c;这…

深入理解 JVM Class文件格式(三)

** JVM常量池中各数据项类型详解 ** 关于常量池的大概内容&#xff0c; 已经在 深入理解 JVM Class文件格式&#xff08;一&#xff09; 中讲解过了&#xff0c; 这篇文章中还介绍了常量池中的11种数据类型。 本文的任务是详细讲解这11种数据类型&#xff0c; 深度剖析源文件…

#6073. 「2017 山东一轮集训 Day5」距离(树链剖分 + 永久标记主席树)

#6073. 「2017 山东一轮集训 Day5」距离 给定一颗有nnn个节点带边权的树&#xff0c;以及一个排列ppp&#xff0c;path(u,v)path(u, v)path(u,v)为u,vu, vu,v路径上的点集&#xff0c;dist(u,v)dist(u, v)dist(u,v)为u,vu, vu,v之间的最短路的长度。 有mmm次询问&#xff0c;…

ML.NET 示例:搜索引擎结果排名

ML.NET 示例中文版&#xff1a;https://github.com/feiyun0112/machinelearning-samples.zh-cn/edit/master/samples/csharp/getting-started/Ranking_Web英文原版请访问&#xff1a;https://github.com/dotnet/machinelearning-samples/tree/master/samples/csharp/getting-st…

深入理解 JVM Class文件格式(四)

&#xff08;3&#xff09;CONSTANT_Integer_info 一个常量池中的CONSTANT_Integer_info数据项, 可以看做是CONSTANT_Integer类型的一个实例。 它存储的是源文件中出现的int型数据的值。 同样&#xff0c; 作为常量池中的一种数据类型&#xff0c; 它的第一个字节也是一个tag值…

.Net Core中使用Quartz.Net Vue开即用的UI管理

Quartz.NETQuartz.Net 定制UI维护了常用作业添加、删除、修改、停止、启动功能&#xff0c;直接使用cron表达式设置作业执行间隔&#xff0c;有完整的日志记录。Quartz.NET是一个功能齐全的开源作业调度系统&#xff0c;可用于从最小的应用程序到大型企业系统。Quartz.NET是一个…

Ancient Distance(妙啊!!!) [2020牛客暑期多校训练营(第四场)]

Ancient Distance 给定一颗根为111有nnn个节点的树&#xff0c;每次可以选定树上kkk节点当作特殊节点&#xff0c; 定义dis(u)dis(u)dis(u)为&#xff0c;从u−>1u->1u−>1遇上的第一个特殊点的距离&#xff0c;如果遇不上特殊点则dis(u)dis(u)dis(u)无穷大。 有nn…

深入理解 JVM Class文件格式(五)

&#xff08;8&#xff09; CONSTANT_Class_info 常量池中的一个CONSTANT_Class_info&#xff0c; 可以看做是CONSTANT_Class数据类型的一个实例。 他是对类或者接口的符号引用。 它描述的可以是当前类型的信息&#xff0c; 也可以描述对当前类的引用&#xff0c; 还可以描述对…