为什么需要新的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示例文件:

针对这个文件,需要修改一下它的属性:

Utf8JsonReader

先使用 Utf8JsonReader 来读取JSON文件。

Utf8JsonReader 并不会读取文件或者stream,它会读取Span数据类型。

直接上代码:

Main方法里面,我们使用File.ReadAllBytes从sample.json文件读取数格式为byte[],然后通过AsSpan这个扩展方法将其转化为Span<byte>数据类型,然后把它传递到 Utf8JsonReader 的构造函数来创建一个JSON的reader。

接下来使用while循环对JSON数据的每个Token进行读取,每次执行Read()方法时,reader就会移动到JSON数据里面的下一个Token那里。

Token分成几种类型,GetTokenInfo方法就是判断一下Token的类型,并返回一些描述性信息,这里面应该是包含了所有的类型。这里面使用到了C# 8 的 switch 表达式。

运行程序

结果如下:

可以看到sample.json文件里面的每个Token都被正确的显示了。

JsonDocument类

JsonDocument是基于Utf8JsonReader 构建的。JsonDocument 可分析 JSON 数据并生成只读文档对象模型 (DOM),可对模型进行查询,以支持随机访问和枚举。使用 JsonDocument 分析常规 JSON 有效负载并访问其所有成员比使用 Json.NET 快 2-3 倍,且为合理大小(即 < 1 MB)的数据所分配的量非常少。

JsonDocument可以处理Span,也可以处理Stream。

例子:

这里我通过File.OpenRead把json文件转化为stream。然后使用JsonDocument.Parse方法把stream解析成JSON文档对象模型。

注意,这里我使用了C# 8的using var语法,这个以后再说。

下面我们开始从这个JSON文档对象模型的根节点开始遍历,也就是RootElement:

然后通过root这个JsonElement类型的对象的GetProperty方法来获得相应的属性,而且这个方法可以连串使用:

最后一行使用GetString方法来获得该属性的字符串值。

然后我们可以写一个递归调用的方法来遍历整个模型的每个属性:

这个方法接受JsonElement类型的对象,然后对该元素的属性进行循环。

如果当前属性是另一个对象,那么就继续递归调用这个方法;

否则就输出原始的文本。

最后调用该方法:

输出结果为:

与json文件的内容匹配。

Utf8JsonWriter类

下面研究一下如何写入json文件。这里需要使用Utf8JsonWriter类。

直接看代码:

这个类需要传递的参数类型是Stream或者Buffer,也就是向Stream或Buffer里面写入数据。

那么就提供一个buffer:

下面单独写一个方法,来生成json数据:

参数类型是Utf8JsonWriter。通过智能提示可以看到它提供了很多用于写入不同类型数据的方法。

写JSON对象

现在我想写一个json对象,那么就从WriteStartObject()开始,然后以WriteEndObject()结束:

这样的话,实际上我已经拥有了一个合法的json文档。

写属性和值

可以分开写属性和值:

也可以同时把属性和值写出来:

显示JSON数据

我先写这些内容,然后在Main方法里面调用一下:

首先需要告诉writer把它的内容flush给buffer,使用这个buffer我们可以获得writer的输出,这样的话就会得到一个byte数组,然后把这个byte数组转化为字符串,这样就可以在控制台显示它了:

运行一下看看效果:

没啥太大的问题,就是格式不好看。

对输出进行格式化

.NET Core提供了一个JsonWriterOptions类,它可以对Writer进行一些设置。

这里对输出进行了缩进,最后把这个options传递给Utf8JsonWriter的构造函数即可。

再次运行:

现在好看多了。

JsonSerializer

前面几节的内容可能稍微有点底层,我们大部分时候可能只需要对C#的类进行串行化或者将JSON数据反串行化成C#类,在.NET Core 3.0里面,我们可以使用JsonSerializer这个类来做这些事情。

例子:

还是使用之前用到的json数据:

然后我们需要建建立两个类,对应这个文件:

反串行化

可以使用JsonSerializer类的Deserialize()方法对json数据反串行化。这个方法支持三种类型的输入参数,分别是:

  • JSON数据的字符串

  • Utf8JsonReader

  • ReadOnlySpan<byte>,它里面包含JSON数据

为了简单一点,我直接把json文件读取成字符串,然后传给Deserialize方法:

然后我试图打印出反串行化之后的一些属性数据。但是这不会成功。因为JSON文件里面数据的大小写命名规范使用的是camel casing(简单理解为首字母是小写的),而默认情况下Deserializer会寻找Pascal casing这种规范(简单理解为每个单词的首字母都是大写的)的属性名。

格式化

为解决这个问题,就需要使用JsonSerializerOptions类:

建立该类的一个实例,设置PropertyNamingPolicy为CamelCase,然后把这个实例传递给Deserialize方法的第二个参数。

运行看结果:

这次就没有问题了。

串行化

JsonSerializer也支持串行化,也就是把C#数据转化为JSON数据:

这里使用了相同的options。

运行结果:

如果想让输出结果更好看一些,可以在JsonSerializerOptions里面进行相应的设置:

这次输出结果为:

总结

总结一下.NET Core 3.0新的JSON API:

  • Utf8JsonReader - 读操作,快速,低级

  • Utf8JsonWriter - 写操作,快速,低级

  • JsonDocument - 基于DOM,快速

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

另外 JSON.NET 仍然被支持。

.NET Core 3.0 里新的JSON API的更多相关文章

  1. HDD成都站:HMS Core 6.0带来新可能 多元服务驱动产品商业成功

    9月10日,由华为开发者联盟主办的HDD(Huawei Developer Day)于成都举行.活动中,华为HMS Core各领域专家重点解读了HMS Core 6.0为开发者带来的多项全新能力,及生 ...

  2. EF Core 6.0的新计划

    今天,我们很兴奋地与你分享Entity Framework Core 6.0的计划. 这个计划汇集了许多人的意见,并概述了我们打算在哪里以及如何优化实体框架(EF Core) 6.0版本.这个计划并不 ...

  3. 在 .NET Core 3.0 中支持 Newtonsoft.Json 的使用

    .NET Core 3.0 已经使用了一整套内置的 Josn 序列化/反序列化方案,而且看上去效率还不错.但对于某些项目必须使用到 Newtonsoft.Json 的时候,就会抛出如下异常: Syst ...

  4. 用ASP.NET Core 2.0 建立规范的 REST API

    什么是REST REST 是 Representational State Transfer 的缩写. 它是一种架构的风格, 这种风格基于一套预定义的规则, 这些规则描述了网络资源是如何定义和寻址的. ...

  5. 用ASP.NET Core 2.0 建立规范的 REST API -- 预备知识 (2) + 准备项目

    上一部分预备知识在这 http://www.cnblogs.com/cgzl/p/9010978.html 如果您对ASP.NET Core很了解的话,可以不看本文, 本文基本都是官方文档的内容. A ...

  6. 用ASP.NET Core 2.0 建立规范的 REST API -- 预备知识

    什么是REST REST 是 Representational State Transfer 的缩写. 它是一种架构的风格, 这种风格基于一套预定义的规则, 这些规则描述了网络资源是如何定义和寻址的. ...

  7. 用ASP.NET Core 2.0 建立规范的 REST API -- 预备知识1

    什么是REST REST 是 Representational State Transfer 的缩写. 它是一种架构的风格, 这种风格基于一套预定义的规则, 这些规则描述了网络资源是如何定义和寻址的. ...

  8. Asp.Net Core 3.0 学习3、Web Api 文件上传 Ajax请求以及跨域问题

    1.创建Api项目 我用的是VS2019 Core3.1 .打开Vs2019 创建Asp.Net Core Web应用程序命名CoreWebApi 创建选择API 在Controller文件夹下面添加 ...

  9. 用ASP.NET Core 2.0 建立规范的 REST API -- DELETE, UPDATE, PATCH 和 Log

    本文所需的一些预备知识可以看这里: http://www.cnblogs.com/cgzl/p/9010978.html 和 http://www.cnblogs.com/cgzl/p/9019314 ...

随机推荐

  1. 字节输出流OutputStream

    1.OutputStream是输出字节流的超类. import java.io.File; import java.io.FileOutputStream; import java.io.IOExce ...

  2. tcp居然会数据延迟40ms被发送

    tcpdump是很好的tcp分析工具,在此配合nc命令来学习tcpdump nc -l 8000 tcpdump -S -n -i lo tcp and host 127.0.0.1 and port ...

  3. Java 截取字符串中指定数据及之后数据

    String resCallBackJson="12556{1{{{456858585{";        resCallBackJson = resCallBackJson.su ...

  4. jenkins构建maven项目:找不到本地依赖包的解决办法

    前言: 我们在构建maven项目时,常常会用到一些特殊的jar包(不能在中央仓库中直接下载到本地仓库如微软不允许以maven的方式直接下载com.microsoft.sqlserver:sqljdbc ...

  5. Spring boot 官网学习笔记 - Configuration Class(@import)

    推荐使用 Java-based configuration ,也可以使用xml we generally recommend that your primary source be a single ...

  6. mysql创建数据库指定字符集和校对规则

    mysql创建数据库的语法格式: CREATE DATABASE [IF NOT EXISTS] <数据库名> [[DEFAULT] CHARACTER SET <字符集名>] ...

  7. springboot 2.1.3.RELEASE版本解析.properties文件配置

    1.有时为了管理一些特定的配置文件,会考虑单独放在一个配置文件中,如redis.properties: #Matser的ip地址 redis.host=192.168.5.234 #端口号 redis ...

  8. freemarker常见语法

    FreeMarker的插值有如下两种类型:1,通用插值${expr};2,数字格式化插值:#{expr}或#{expr;format}  ${basketball.name?if_exists } / ...

  9. 痞子衡嵌入式:飞思卡尔i.MX RTyyyy系列MCU特性那些事(5)- 划时代新品RT1170

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔i.MX RTyyyy系列MCU的划时代新品i.MXRT1170. 自2017年开始,每年的6月25日恩智浦都会在北京举行微控制 ...

  10. .Net Core自动化部署系列(二):使用Jenkins打造镜像发布流水线

    一.简介 之前写过一篇关于Jenkins搭配GitLab实现.net core项目自动发布到IIS的博文,比较简单哈,只是个Demo.本篇我们将会使用Jenkins搭配GitLab实现镜像的自动打包和 ...