.NET Core 3.0提供了一个名为System.Text.Json的全新命名空间,它支持reader/writer,文档对象模型(DOM)和序列化程序。在此博客文章中,我将介绍它如何工作以及如何使用。

官方文档

获取JSON库

  • 如果以.NET Core为目标,请安装.NET Core 3.0及以上版本,该版本提供了新的JSON库和ASP.NET Core集成。
  • 如果以.NET Standard或.NET Framework为目标。安装System.Text.Json NuGet软件包(确保安装.NET Framework4.6.0或更高版本)。为了与ASP.NET Core集成,必须以.NET Core 3.0为目标。

NET Core 3.0中JSON特性

新的JSON API通过使用Span进行性能优化,并且可以直接处理UTF-8,而无需转码为UTF-16 string 实例。这两个方面对于ASP.NET Core都是至关重要的,在ASP.NET Core中,吞吐量是关键要求。使用System.Text.Json,可以将速度提高大约1.3倍至5倍。

使用System.Text.Json

using System.Text.Json;
using System.Text.Json.Serialization;

使用序列化器Serializer

  • 学习.Net Core最好的方式是查看源码,下面是JsonSerializer Serialize的部分源码:
namespace System.Text.Json
{
public static partial class JsonSerializer
{
/// <summary>
/// Convert the provided value into a <see cref="System.String"/>.
/// </summary>
/// <returns>A <see cref="System.String"/> representation of the value.</returns>
/// <param name="value">The value to convert.</param>
/// <param name="options">Options to control the conversion behavior.</param>
/// <remarks>Using a <see cref="System.String"/> is not as efficient as using UTF-8
/// encoding since the implementation internally uses UTF-8. See also <see cref="SerializeToUtf8Bytes"/>
/// and <see cref="SerializeAsync"/>.
/// </remarks>
public static string Serialize<TValue>(TValue value, JsonSerializerOptions options = null)
{
return ToStringInternal(value, typeof(TValue), options);
} /// <summary>
/// Convert the provided value into a <see cref="System.String"/>.
/// </summary>
/// <returns>A <see cref="System.String"/> representation of the value.</returns>
/// <param name="value">The value to convert.</param>
/// <param name="inputType">The type of the <paramref name="value"/> to convert.</param>
/// <param name="options">Options to control the conversion behavior.</param>
/// <remarks>Using a <see cref="System.String"/> is not as efficient as using UTF-8
/// encoding since the implementation internally uses UTF-8. See also <see cref="SerializeToUtf8Bytes"/>
/// and <see cref="SerializeAsync"/>.
/// </remarks>
public static string Serialize(object value, Type inputType, JsonSerializerOptions options = null)
{
VerifyValueAndType(value, inputType); return ToStringInternal(value, inputType, options);
} private static string ToStringInternal(object value, Type inputType, JsonSerializerOptions options)
{
return WriteCoreString(value, inputType, options);
}
}
}

可以看到序列化最终调用的是ToStringInternal这个方法。

  • 示例
class Sample
{
public DateTimeOffset Date { get; set; }
public string Summary { get; set; }
} string Serialize(Sample value)
{
return JsonSerializer.Serialize<Sample>(value);
}
//obj
string SerializeObj(object value)
{
return JsonSerializer.Serialize(value);
}

JsonSerializerOptions用于在序列化时设置配置, 例如处理注释,null处理,尾随逗号和命名策略。

 public static string ToJson(this object obj)
{
var options = new JsonSerializerOptions() { IgnoreNullValues = true, WriteIndented = true, AllowTrailingCommas = true };
return JsonSerializer.Serialize(obj, options);
}

使用反序列化器Deserialize

 Sample Deserialize(string json)
{
var options = new JsonSerializerOptions
{
AllowTrailingCommas = true
}; return JsonSerializer.Deserialize<Sample>(json, options);
}

自定义属性来控制序列化行为

可以使用自定义属性来控制序列化行为,例如,忽略属性或者指定属性的名称:

class Sample
{
//忽略
[JsonIgnore]
public DateTimeOffset Date { get; set; }
//指定名称
[JsonPropertyName("test")]
public string Summary { get; set; }
}

使用DOM

有时,不想反序列化JSON但仍然希望对其内容进行结构化访问,这时可以使用JsonDocument

var options = new JsonDocumentOptions
{
AllowTrailingCommas = true
};
using (JsonDocument document = JsonDocument.Parse(json, options))
{
//todo
foreach (JsonElement element in document.RootElement.EnumerateArray())
{
DateTimeOffset date = element.GetProperty("date").GetDateTimeOffset();
//todo
}
}

使用Utf8JsonWriter

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.WriteEndObject();
} string json = Encoding.UTF8.GetString(stream.ToArray());
Console.WriteLine(json);
}

使用Utf8JsonReader

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;
}
} Console.WriteLine();
}

System.Text.Json中的DateTime和DateTimeOffset支持

The System.Text.Json library parses and writes DateTime and DateTimeOffset values according to the ISO 8601:-2019 extended profile. Converters provide custom support for serializing and deserializing with JsonSerializer. Custom support can also be implemented when using Utf8JsonReader and Utf8JsonWriter.

具体请参考官方文档

示例:

 public class DateTimeConverterUsingDateTimeParse : JsonConverter<DateTime>
{
/// <summary>
/// 日期格式
/// </summary>
public string dateTimeFormat { get; }
/// <summary>
/// ctor
/// </summary>
/// <param name="dateTimeFormat"></param>
public DateTimeConverterUsingDateTimeParse(string dateTimeFormat)
{
this.dateTimeFormat = dateTimeFormat;
}
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
Debug.Assert(typeToConvert == typeof(DateTime));
return DateTime.Parse(reader.GetString());
} public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString(dateTimeFormat));
}
}
 public static class JsonHelper
{
/// <summary>Converts to json.</summary>
/// <param name="obj">The object.</param>
/// <param name="dateTimeFormat">The date time format.</param>
/// <returns>System.String.</returns>
public static string ToJson(this object obj, string dateTimeFormat = "yyyy-MM-dd")
{
var options = new JsonSerializerOptions() { IgnoreNullValues = true, WriteIndented = true };
options.Converters.Add(new DateTimeConverterUsingDateTimeParse(dateTimeFormat));
return JsonSerializer.Serialize(obj, options);
}
}

总结

  • 在.NET Core 3.0中,System.Text.Json API提供对JSON的内置支持,包括reader/writer,只读DOM和序列化器/反序列化器。
  • 主要目标是实现高性能和低内存分配。
  • ASP.NET Core 3.0包括对System.Text.Json的支持,默认情况下启用。

补充

有博友提问了下图中的几个问题:

当前API版本反序列化不会将JSON字符串中的数字强制转换;但是JsonConverter转换器功能可以逐个属性有效地选择转换:

public class NumberToStringConverter : JsonConverter<int>
{
public override int Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var number = 0;
if (reader.TokenType == JsonTokenType.String)
{
if (Int32.TryParse(reader.GetString(), out number))
return number;
}
return reader.GetInt32();
} public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
}
} class Sample
{
public string Date { get; set; }
public int Summary { get; set; }
}
var json = "{\"Date\":\"2019-10-31\",\"Summary\":\"1\"}";
var options = new JsonSerializerOptions() { IgnoreNullValues = true, WriteIndented = true };
options.Converters.Add(new NumberToStringConverter());
var deserialize = JsonSerializer.Deserialize<Sample>(json, options);

当前API版本支持System.Text.Json 支持Dictionary<key,value>序列化。

Dictionary<string, object> dictionary = new Dictionary<string, object>
{
{"1", 2}
};
var serialize = JsonSerializer.Serialize(dictionary);
var temjson = "{\"1\":2}";
var deserializeDictionary = JsonSerializer.Deserialize<Dictionary<string, object>>(temjson);

在.Net Core 3.0中尝试新的System.Text.Json API的更多相关文章

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

    译注 可能有的小伙伴已经知道了,在.NET Core 3.0中微软加入了对JSON的内置支持. 一直以来.NET开发者们已经习惯使用Json.NET这个强大的库来处理JSON. 那么.NET为什么要增 ...

  2. 【译】.NET Core 3.0 中的新变化

    .NET Core 3.0 是 .NET Core 平台的下一主要版本.本文回顾了 .Net Core 发展历史,并展示了它是如何从基本支持 Web 和数据工作负载的版本 1,发展成为能够运行 Web ...

  3. [转]【译】.NET Core 3.0 中的新变化

    .NET Core 3.0 是 .NET Core 平台的下一主要版本.本文回顾了 .Net Core 发展历史,并展示了它是如何从基本支持 Web 和数据工作负载的版本 1,发展成为能够运行 Web ...

  4. ASP.NET Core 3.0中使用动态控制器路由

    原文:Dynamic controller routing in ASP.NET Core 3.0 作者:Filip W 译文:https://www.cnblogs.com/lwqlun/p/114 ...

  5. 在Asp.Net Core 3.0中如何使用 Newtonsoft.Json 库序列化数据

    在.Net Core 3.0中 内置了一套Json序列化/反序列化方案,默认可以不再依赖,不再支持   Newtonsoft.Json. 但是.NET Core 3.0 System.Text.Jso ...

  6. .NET Core 3.0 System.Text.Json 和 Newtonsoft.Json 行为不一致问题及解决办法

    行为不一致 .NET Core 3.0 新出了个内置的 JSON 库, 全名叫做尼古拉斯 System.Text.Json - 性能更高占用内存更少这都不是事... 对我来说, 很多或大或小的项目能少 ...

  7. .net core中关于System.Text.Json的使用

    在.Net Framework的时候序列化经常使用Newtonsoft.Json插件来使用,而在.Net Core中自带了System.Text.Json,号称性能更好,今天抽空就来捣鼓一下. 使用起 ...

  8. 探索 ASP.Net Core 3.0系列三:ASP.Net Core 3.0中的Service provider validation

    前言:在本文中,我将描述ASP.NET Core 3.0中新的“validate on build”功能. 这可以用来检测您的DI service provider是否配置错误. 具体而言,该功能可检 ...

  9. 避免在ASP.NET Core 3.0中为启动类注入服务

    本篇是如何升级到ASP.NET Core 3.0系列文章的第二篇. Part 1 - 将.NET Standard 2.0类库转换为.NET Core 3.0类库 Part 2 - IHostingE ...

随机推荐

  1. JAVA设计模式-动态代理(Proxy)源码分析

    在文章:JAVA设计模式-动态代理(Proxy)示例及说明中,为动态代理设计模式举了一个小小的例子,那么这篇文章就来分析一下源码的实现. 一,Proxy.newProxyInstance方法 @Cal ...

  2. Github 持续化集成 工作流 Npm包自动化发布

    Github 持续化集成 工作流 Npm包自动化发布 简介   持续集成指的是,频繁地(一天多次)将代码集成到主干. 它的好处主要有两个: 快速发现错误.每完成一点更新,就集成到主干,可以快速发现错误 ...

  3. [python]python的异常处理

    异常处理:首先了解异常,程序出现逻辑错误或者用户输入不合法都会引发异常,而这些异常并不是致命的所以不会导致程序崩溃死掉.可以利用Python提供的异常处理机制在异常出现时及时捕获,并从内部自我消化. ...

  4. 今天第一次解决了程序在未装VS和XP下运行的问题

    http://www.cnblogs.com/zero5/p/3162948.html  一位素不相识的朋友做的代码雨屏保程序 - 残雪孤侠 - 博客园   上面是我的BLOG 群共享里,有程序和代码 ...

  5. springboot WebMvcConfigurerAdapter替代

    过时应用: @Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter { @Override public vo ...

  6. 【SQL server初级】SQL Server 2005 实现数据库同步备份 过程--结果---分析

    数据库复制:   简单来说,数据库复制就是由两台服务器,主服务器和备份服务器,主服务器修改后,备份服务器自动修改. 复制的模式有两种:推送模式和请求模式,推送模式是主服务器修改后,自动发给备份服务器, ...

  7. 利用百度云接口实现车牌识别·python

    一个小需求---实现车牌识别. 目前有两个想法 1. 调云在线的接口或者使用SDK做开发(配置环境和变异第三方库麻烦,当然使用python可以避免这些问题) 2. 自己实现车牌识别算法(复杂) 一开始 ...

  8. 002-python函数、高级特性

    1.函数 1.1 定义函数 在Python中,定义一个函数要使用def语句,依次写出函数名.括号.括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回 自定义一个求绝对 ...

  9. JavaScript系列:函数式编程(开篇)

    前言: 上一篇介绍了 函数回调,高阶函数以及函数柯里化等高级函数应用,同时,因为正在学习JavaScript·函数式编程,想整理一下函数式编程中,对于我们日常比较有用的部分. 为什么函数式编程很重要? ...

  10. Scala 学习笔记之函数(3)

    class student{ def sayHello(name: => String){ println(s"Hello, $name, welcome $name") } ...