尝试新的 System.Text.Json 源生成器
尝试新的 System.Text.Json 源生成器
在 .NET 6.0 的预览版中,我们使用 System.Text.Json 发布了一个新的 C# source generator 来帮助改进应用程序的性能。这里我们将回顾为什么我们要构建它,以及在你的应用程序中可以获得何种优势。
对于 System.Text.Json 源生成器,在 .NET 中,我们现在有一些用于 JSON 序列化的模型可供选择, JsonSerializer 是现有的模型,提供运行时反射支持,另外有两个编译时的源生成模型;这种方式的生成器生成优化后的序列化模型。或者两者都有。在所有的源生成场景中,生成的组件被直接传送给 JsonSerializer 做性能优化。下面是每种序列化模型提供的功能概览。
JsonSerializer | JsonSerializer + pre-generatiing optimized serialization login | JsonSerializer + pre-generating data access model | |
---|---|---|---|
Increases serialization throughput | No | Yes | No |
Reduces start-up time | No | Yes | Yes |
Reduces private memory usage | No | Yes | Yes |
Eliminates runtime reflection | No | Yes | Yes |
Facilitates trim-safe app size reduction | No | Yes | Yes |
Supports all serialization features | Yes | No | Yes |
源生成器入门
源生成器可以用于任何 .NET 的 C# 项目,包括控制台应用,类库,Web 应用,以及 Blazor 应用程序。可以通过 System.TExt.Json 的 NuGet 包。在 .NET 6.0 即将到来的预览版 7 中将不再需要。
除了 .NET 6.0,源生成器与其它的 TFM 兼容,即 .NET 5.0 和更低的版本,.NET Framework 和 .NET Standard。API 集在各种 TFM 之间是一致的,但是不同 TFM 的可用的框架 API 不同,内部的实现是不同的。
对 .NET SDK 来说,最低的支持版本是 .NET 5.0
什么是 System.Txt.Json 源生成器
几乎所有的 .NET 序列化器的核心都是反射。反射对于特定场景提供了优异的能力,但是不包括作为高性能云原生应用程序 (特别) 基础的序列化/反序列,以及处理大量的 JSON 文档的场景。对于启动、内存使用和程序集修剪,反射都是问题所在。
一种方案是将运行时反射替换为编译时源生成。源生成器生成 C# 源代码文件,它可以被编译为库或者应用程序的一部分。在编译时生成代码对于 .NET 应用程序可以带来许多优势,包括增强性能。在 .NET 6 中,作为 System.Text.Json 的一部分,我们包括了新的源生成器。JSON 源生成器与 JsonSerializer 协同工作,可以通过多种方式配置。现有的 JsonSerializer 功能不变,所以是否使用新的源生成器是你的选择。JSON 源生成器的工作方式是将 JSON 可序列化类型的运行时检查转换到编译时,它生成一个静态模型来访问这些类型中的数据,直接使用 Utf8JsonWriter 优化序列化逻辑,或者同时使用两者。
为了使用源生成器,你可以定义一个派生于被称为 JsonSerializerContext 的新类型的分部类,使用新的 JsonSerializableAttribute 类来标注可序列化类型。
例如,对于一个简单的 Person 类型进行序列化。
namespace Test
{
internal class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
}
需要为源生成器如下指定类型。
using System.Text.Json.Serialization;
namespace Test
{
[JsonSerializable(typeof(Person))]
internal partial class MyJsonContext : JsonSerializerContext
{
}
}
作为构建过程的一部分,源生成器会将 MyJsonContext 分部类填充为如下类型。
internal partial class MyJsonContext : JsonSerializerContext
{
public static MyJsonContext Default { get; }
public JsonTypeInfo<Person> Person { get; }
public MyJsonContext(JsonSerializerOptions options) { }
public override JsonTypeInfo GetTypeInfo(Type type) => ...;
}
生成的源代码可以通过将它直接传递给 JsonSerializer 的新的重载方法中,以集成到编译的应用程序中。
// 序列化
Person person = new() { FirstName = "Jane", LastName = "Doe" };
byte[] utf8Json = JsonSerializer.SerializeToUtf8Bytes(
person, MyJsonContext.Default.Person);
// 反序列化
person = JsonSerializer.Deserialize(utf8Json, MyJsonContext.Default.Person):
为什么使用源生成器?
JsonSerializer 是将 .NET 对象序列化到 JSON 串,以及从 JSON 串反序列回到 .NET 对象的工具。为了处理某种类型,序列化器需要得到如何访问对象成员的信息。在序列化的时候,序列化器需要访问对象的属性和字段读取器。简单来说,在反序列化的时候,序列化器需要访问构造函数来实例化对象,以及对象的字段与属性的设置器。
System.Text.Json 暴露在使用 JsonSerializer 进行序列化和反序列化时影响的机制,通过 JsonSerializerOptions (它支持运行时配置),还可以通过像 [JsonPropertyName(string)] 与 [JsonIgnore] 这样的特性 ( 这支持设计时配置 )。在序列化和反序列化类型的实例的时候,序列化器需要这些配置的信息,以便其使用。
当处理 JSON 可序列化类型的时候,序列化器需要在一个结构中访问关于对象成员和特性的配置信息,优化的格式。我们可以引用此结构化的信息作为必要的序列化元数据来序列化类型。
在以前版本的 System.Text.Json 中,序列化元数据只能在运行时得出,在对每种类型进行第一次序列化和反序列化的时候得出传递给序列化器。在这些元数据生成之后,序列化器执行实际的序列化和反序列化。这里得到的元数据将被缓存并在后继的 JSON 处理中被重用。生成元数据的环节基于反射实现,计算的复杂性在事件和分配上都是昂贵的。我们可以将该阶段称为序列化器的 “热身” 阶段。
System.Text.Json 源生成器帮助我们移除了该热身阶段,通过将运行时中的使用反射的可序列化类型检查转移到编译时进行。检查的结果可以作为源代码,用来初始化结构化的序列化元数据实例。生成器还可以生成高度优化的序列化逻辑,得益于一套 序列特性,指定的预先处理,默认情况下,生成器生成两种类型的源,但是可以配置为仅仅生成一套类型,或者每种可序列化类型一种。
生成的元数据包含在编译生成的程序集中,可以被初始化并直接传递给 JsonSerializer 以便序列化器不需要在运行时生成。这有助于缩减每种类型第一次序列化或者反序列化的时间。使用这些特性,使用该源生成器可以提供如下优势:
- 增强序列化的吞吐量
- 缩减启动时间
- 缩减私有内存的使用
- 移除对 System.Reflection 和 System.Reflection.Emit 的使用
- 剪裁兼容的序列化,可以缩减应用程序的尺寸
JsonTypeInfo<T>
, JsonTypeInfo
, 与JsonSerializerContext 简介
Try the new System.Text.Json source generator | .NET Blog (microsoft.com)
尝试新的 System.Text.Json 源生成器的更多相关文章
- 在.Net Core 3.0中尝试新的System.Text.Json API
.NET Core 3.0提供了一个名为System.Text.Json的全新命名空间,它支持reader/writer,文档对象模型(DOM)和序列化程序.在此博客文章中,我将介绍它如何工作以及如何 ...
- [译]试用新的System.Text.Json API
译注 可能有的小伙伴已经知道了,在.NET Core 3.0中微软加入了对JSON的内置支持. 一直以来.NET开发者们已经习惯使用Json.NET这个强大的库来处理JSON. 那么.NET为什么要增 ...
- .NET Core 内置的 System.Text.Json 使用注意
System.Text.Json 是 .NET Core 3.0 新引入的高性能 json 解析.序列化.反序列化类库,武功高强,但毕竟初入江湖,炉火还没纯青,使用时需要注意,以下是我们在实现使用中遇 ...
- .NET Core 3.0 System.Text.Json 和 Newtonsoft.Json 行为不一致问题及解决办法
行为不一致 .NET Core 3.0 新出了个内置的 JSON 库, 全名叫做尼古拉斯 System.Text.Json - 性能更高占用内存更少这都不是事... 对我来说, 很多或大或小的项目能少 ...
- [.Net Core 3.0+/.Net 5] System.Text.Json中时间格式化
简介 .Net Core 3.0开始全新推出了一个名为System.Text.Json的Json解析库,用于序列化和反序列化Json,此库的设计是为了取代Json.Net(Newtonsoft.Jso ...
- 【译】System.Text.Json 的下一步是什么
.NET 5.0 最近发布了,并带来了许多新特性和性能改进.System.Text.Json 也不例外.我们改进了性能和可靠性,并使熟悉 Newtonsoft.Json 的人更容易采用它.在这篇文章中 ...
- 使用.Net6中的System.Text.Json遇到几个常见问题及解决方案
前言 以前.NetCore是不内置JSON库的,所以大家都用Newtonsoft的JSON库,而且也确实挺好用的,不过既然官方出了标准库,那更方便更值得我们多用用,至少不用每次都nuget安装Newt ...
- 使用System.Text.Json处理Json文档以及部分坑
System.Text.Json处理Json文档需要用到JsonDocument,JsonElement,JsonProperty. JsonDocument就是一个表示Json文档的东西,JsonE ...
- .netcore3.0 System.Text.Json 日期格式化
.netcore3.0 的json格式化不再默认使用Newtonsoft.Json,而是使用自带的System.Text.Json来处理. 理由是System.Text.Json 依赖更少,效率更高. ...
- In .net 4.8,calculate the time cost of serialization in BinaryFormatter,NewtonSoft.json,and System.Text.Json.JsonSerializer.Serialize
using ConsoleApp390.Model; using Newtonsoft.Json; using System; using System.Collections.Generic; us ...
随机推荐
- WebBrowser中打开新页面
要求新打开的网页受控于WebBrowser 解决办法很简单,分两情况,一是在当前WebBrowser中打开新页面,二是在新Form中的WebBrowser中打开新页面: public Form1() ...
- USB协议详解第8讲(USB描述符-字符串和语言ID描述符)
1.字符串描述符相关概念 字符串描述符:首先,字符串描述符就是用字符串描述一个设备的一些属性,毕竟人能看懂的是字符,而不是十六进制,描述的属性包括设备厂商名字.产品名字.产品序列号.各个配置名字.各个 ...
- OOP的核心思想
1. 封装 既是信息封装,把一些信息进行封装成对象,只保留部分接口和方法与外部联系,能有效避免程序间相互依赖,实现代码模块间松藕合 : 2. 继承 子类自动继承父类的属性和方法,继承实现了代码的重用性 ...
- 封装 axios 拦截器
import axios from "axios"; // 自定义一个 request 实例 const request = axios.create({ baseURL: &qu ...
- 强化学习笔记之【SAC算法】
强化学习笔记之[SAC算法] 前言: 本文为强化学习笔记第四篇,第一篇讲的是Q-learning和DQN,第二篇DDPG,第三篇TD3 TD3比DDPG少了一个target_actor网络,其它地方有 ...
- tekton初次安装报错“containers with incomplete status: [place-tools]”
报错内容 在按照官方部署方式部署完毕以后,执行第一个taskrun的时候就报错了,报错如下 Status: Conditions: Last Transition Time: 2022-08-08T0 ...
- Docker挂载jar包运行脚本
下载镜像 docker pull openjdk:8 执行命令 docker run -d -p 9001:8081 -v /opt/springboot-docker-1.0.jar:/var/li ...
- KubeSphere 在互联网电商行业的应用实践
来自社区用户(SRE运维手记)投稿 背景 在云原生的时代背景下,Kubernetes 已经成为了主流选择.然而,Kubernetes 的原生操作复杂性和学习曲线较高,往往让很多团队在使用和管理上遇到挑 ...
- 什么是APP原生开发
什么是APP原生开发?原生App实际上是一种基于智能手机本地操作系统如Android.IOS并且使用原生程序编写运行的第三方移动应用程序.开发原生App软件需要针对不同智能手机的操作系统来选择不同的A ...
- Machine Learning Week_1 Model and Cost Function 1-4
目录 2 Model and Cost Function 2.1 Video: Model Representation unfamiliar words 2.2 Reading: Model Rep ...