.NET Core 3.0提供了一个名为System.Text.Json的全新命名空间,它支持reader/writer,文档对象模型(DOM)和序列化程序。在此博客文章中,我将介绍它如何工作以及如何使用。
如果以.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为目标。
新的JSON API通过使用Span进行性能优化,并且可以直接处理UTF-8,而无需转码为UTF-16 string 实例。这两个方面对于ASP.NET Core都是至关重要的,在ASP.NET Core中,吞吐量是关键要求。使用System.Text.Json,可以将速度提高大约1.3倍至5倍。
学习.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); }可以使用自定义属性来控制序列化行为,例如,忽略属性或者指定属性的名称:
class Sample { //忽略 [JsonIgnore] public DateTimeOffset Date { get; set; } //指定名称 [JsonPropertyName("test")] public string Summary { get; set; } }有时,不想反序列化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 } }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);相关文章: